style: ssh包移动
This commit is contained in:
@@ -13,9 +13,9 @@ import (
|
|||||||
"be.ems/src/framework/config"
|
"be.ems/src/framework/config"
|
||||||
"be.ems/src/framework/datasource"
|
"be.ems/src/framework/datasource"
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/utils/crypto"
|
"be.ems/src/framework/utils/crypto"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
systemService "be.ems/src/modules/system/service"
|
systemService "be.ems/src/modules/system/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
"be.ems/src/framework/utils/cmd"
|
|
||||||
"be.ems/src/framework/utils/parse"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileListRow 文件列表行数据
|
|
||||||
type FileListRow struct {
|
|
||||||
FileType string `json:"fileType"` // 文件类型 dir, file, symlink
|
|
||||||
FileMode string `json:"fileMode"` // 文件的权限
|
|
||||||
LinkCount int64 `json:"linkCount"` // 硬链接数目
|
|
||||||
Owner string `json:"owner"` // 所属用户
|
|
||||||
Group string `json:"group"` // 所属组
|
|
||||||
Size string `json:"size"` // 文件的大小
|
|
||||||
ModifiedTime int64 `json:"modifiedTime"` // 最后修改时间,单位为秒
|
|
||||||
FileName string `json:"fileName"` // 文件的名称
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件列表
|
|
||||||
// search 文件名后模糊*
|
|
||||||
//
|
|
||||||
// return 行记录,异常
|
|
||||||
func FileList(sshClient *ConnSSH, path, search string) ([]FileListRow, error) {
|
|
||||||
var rows []FileListRow
|
|
||||||
rowStr := ""
|
|
||||||
|
|
||||||
// 发送命令
|
|
||||||
searchStr := "*"
|
|
||||||
if search != "" {
|
|
||||||
searchStr = search + searchStr
|
|
||||||
}
|
|
||||||
// cd /var/log && find. -maxdepth 1 -name'mme*' -exec ls -lthd --time-style=+%s {} +
|
|
||||||
cmdStr := fmt.Sprintf("cd %s && find . -maxdepth 1 -name '%s' -exec ls -lthd --time-style=+%%s {} +", path, searchStr)
|
|
||||||
// cd /var/log && ls -lthd --time-style=+%s mme*
|
|
||||||
// cmdStr := fmt.Sprintf("cd %s && ls -lthd --time-style=+%%s %s", path, searchStr)
|
|
||||||
|
|
||||||
// 是否远程客户端读取
|
|
||||||
if sshClient == nil {
|
|
||||||
resultStr, err := cmd.Exec(cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
|
||||||
return rows, err
|
|
||||||
}
|
|
||||||
rowStr = resultStr
|
|
||||||
} else {
|
|
||||||
resultStr, err := sshClient.RunCMD(cmdStr)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Ne FileList Path: %s, Search: %s, Error:%s", path, search, err.Error())
|
|
||||||
return rows, err
|
|
||||||
}
|
|
||||||
rowStr = resultStr
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历组装
|
|
||||||
rowStrList := strings.Split(rowStr, "\n")
|
|
||||||
for _, rowStr := range rowStrList {
|
|
||||||
if rowStr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// 使用空格对字符串进行切割
|
|
||||||
fields := strings.Fields(rowStr)
|
|
||||||
|
|
||||||
// 拆分不足7位跳过
|
|
||||||
if len(fields) != 7 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件类型
|
|
||||||
fileMode := fields[0]
|
|
||||||
fileType := "file"
|
|
||||||
if fileMode[0] == 'd' {
|
|
||||||
fileType = "dir"
|
|
||||||
} else if fileMode[0] == 'l' {
|
|
||||||
fileType = "symlink"
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件名
|
|
||||||
fileName := fields[6]
|
|
||||||
if fileName == "." {
|
|
||||||
continue
|
|
||||||
} else if strings.HasPrefix(fileName, "./") {
|
|
||||||
fileName = strings.TrimPrefix(fileName, "./")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提取各个字段的值
|
|
||||||
rows = append(rows, FileListRow{
|
|
||||||
FileMode: fileMode,
|
|
||||||
FileType: fileType,
|
|
||||||
LinkCount: parse.Number(fields[1]),
|
|
||||||
Owner: fields[2],
|
|
||||||
Group: fields[3],
|
|
||||||
Size: fields[4],
|
|
||||||
ModifiedTime: parse.Number(fields[5]),
|
|
||||||
FileName: fileName,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return rows, nil
|
|
||||||
}
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
gosftp "github.com/pkg/sftp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SSHClientSFTP SSH客户端SFTP对象
|
|
||||||
type SSHClientSFTP struct {
|
|
||||||
Client *gosftp.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close 关闭会话
|
|
||||||
func (s *SSHClientSFTP) Close() {
|
|
||||||
if s.Client != nil {
|
|
||||||
s.Client.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyDirRemoteToLocal 复制目录-远程到本地
|
|
||||||
func (s *SSHClientSFTP) CopyDirRemoteToLocal(remoteDir, localDir string) error {
|
|
||||||
// 创建本地目录
|
|
||||||
err := os.MkdirAll(localDir, 0775)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyDirRemoteToLocal failed to creating local directory %s: => %s", localDir, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列出远程目录中的文件和子目录
|
|
||||||
remoteFiles, err := s.Client.ReadDir(remoteDir)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyDirRemoteToLocal failed to reading remote directory %s: => %s", remoteDir, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 遍历远程文件和子目录并复制到本地
|
|
||||||
for _, remoteFile := range remoteFiles {
|
|
||||||
remotePath := filepath.ToSlash(filepath.Join(remoteDir, remoteFile.Name()))
|
|
||||||
localPath := filepath.ToSlash(filepath.Join(localDir, remoteFile.Name()))
|
|
||||||
|
|
||||||
if remoteFile.IsDir() {
|
|
||||||
// 如果是子目录,则递归复制子目录
|
|
||||||
err = s.CopyDirRemoteToLocal(remotePath, localPath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyDirRemoteToLocal failed to copying remote directory %s: => %s", remotePath, err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果是文件,则复制文件内容
|
|
||||||
if err := s.CopyFileRemoteToLocal(remotePath, localPath); err != nil {
|
|
||||||
logger.Errorf("CopyDirRemoteToLocal failed to opening remote file %s: => %s", remotePath, err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyDirLocalToRemote 复制目录-本地到远程
|
|
||||||
func (s *SSHClientSFTP) CopyDirLocalToRemote(localDir, remoteDir string) error {
|
|
||||||
// 遍历本地目录中的文件和子目录并复制到远程
|
|
||||||
err := filepath.Walk(localDir, func(localPath string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成远程路径
|
|
||||||
remotePath := filepath.ToSlash(filepath.Join(remoteDir, localPath[len(localDir):]))
|
|
||||||
|
|
||||||
if info.IsDir() {
|
|
||||||
// 如果是子目录,则创建远程目录
|
|
||||||
if err := s.Client.MkdirAll(remotePath); err != nil {
|
|
||||||
logger.Errorf("CopyDirLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 如果是文件,则复制文件内容
|
|
||||||
if err := s.CopyFileLocalToRemote(localPath, remotePath); err != nil {
|
|
||||||
logger.Errorf("CopyDirLocalToRemote failed to copying remote file %s: => %s", localPath, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyDirLocalToRemote failed to walking remote directory: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyFileRemoteToLocal 复制文件-远程到本地
|
|
||||||
func (s *SSHClientSFTP) CopyFileRemoteToLocal(remotePath, localPath string) error {
|
|
||||||
if err := os.MkdirAll(filepath.Dir(localPath), 0775); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 打开远程文件
|
|
||||||
remoteFile, err := s.Client.Open(remotePath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyFileRemoteToLocal failed to opening remote file: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer remoteFile.Close()
|
|
||||||
|
|
||||||
// 创建本地文件
|
|
||||||
localFile, err := os.Create(localPath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyFileRemoteToLocal failed to creating local file: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer localFile.Close()
|
|
||||||
|
|
||||||
// 复制文件内容
|
|
||||||
if _, err = io.Copy(localFile, remoteFile); err != nil {
|
|
||||||
logger.Errorf("CopyFileRemoteToLocal failed to copying contents: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CopyFileLocalToRemote 复制文件-本地到远程
|
|
||||||
func (s *SSHClientSFTP) CopyFileLocalToRemote(localPath, remotePath string) error {
|
|
||||||
// 打开本地文件
|
|
||||||
localFile, err := os.Open(localPath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyFileLocalToRemote failed to opening local file: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer localFile.Close()
|
|
||||||
|
|
||||||
// 创建远程目录
|
|
||||||
if err := s.Client.MkdirAll(filepath.Dir(remotePath)); err != nil {
|
|
||||||
logger.Errorf("CopyFileLocalToRemote failed to creating remote directory %s: => %s", remotePath, err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建远程文件
|
|
||||||
remoteFile, err := s.Client.Create(remotePath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CopyFileLocalToRemote failed to creating remote file: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer remoteFile.Close()
|
|
||||||
|
|
||||||
// 复制文件内容
|
|
||||||
if _, err = io.Copy(remoteFile, localFile); err != nil {
|
|
||||||
logger.Errorf("CopyFileLocalToRemote failed to copying contents: => %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,229 +0,0 @@
|
|||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
|
||||||
"be.ems/src/framework/utils/cmd"
|
|
||||||
gosftp "github.com/pkg/sftp"
|
|
||||||
gossh "golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ConnSSH 连接SSH对象
|
|
||||||
type ConnSSH struct {
|
|
||||||
User string `json:"user"` // 主机用户名
|
|
||||||
Addr string `json:"addr"` // 主机地址
|
|
||||||
Port int64 `json:"port"` // SSH端口
|
|
||||||
AuthMode string `json:"authMode"` // 认证模式(0密码 1主机私钥)
|
|
||||||
Password string `json:"password"` // 认证密码
|
|
||||||
PrivateKey string `json:"privateKey"` // 认证私钥
|
|
||||||
PassPhrase string `json:"passPhrase"` // 认证私钥密码
|
|
||||||
|
|
||||||
DialTimeOut time.Duration `json:"dialTimeOut"` // 连接超时断开
|
|
||||||
|
|
||||||
Client *gossh.Client `json:"client"`
|
|
||||||
LastResult string `json:"lastResult"` // 记最后一次执行命令的结果
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient 创建SSH客户端
|
|
||||||
func (c *ConnSSH) NewClient() (*ConnSSH, error) {
|
|
||||||
// IPV6地址协议
|
|
||||||
proto := "tcp"
|
|
||||||
if strings.Contains(c.Addr, ":") {
|
|
||||||
proto = "tcp6"
|
|
||||||
c.Addr = fmt.Sprintf("[%s]", c.Addr)
|
|
||||||
}
|
|
||||||
addr := fmt.Sprintf("%s:%d", c.Addr, c.Port)
|
|
||||||
|
|
||||||
// ssh客户端配置
|
|
||||||
config := &gossh.ClientConfig{}
|
|
||||||
config.SetDefaults()
|
|
||||||
config.HostKeyCallback = gossh.InsecureIgnoreHostKey()
|
|
||||||
config.User = c.User
|
|
||||||
|
|
||||||
// 默认等待5s
|
|
||||||
if c.DialTimeOut == 0 {
|
|
||||||
c.DialTimeOut = 5 * time.Second
|
|
||||||
}
|
|
||||||
config.Timeout = c.DialTimeOut
|
|
||||||
|
|
||||||
// 认证模式-0密码 1私钥
|
|
||||||
if c.AuthMode == "1" {
|
|
||||||
var signer gossh.Signer
|
|
||||||
var err error
|
|
||||||
if len(c.PassPhrase) != 0 {
|
|
||||||
signer, err = gossh.ParsePrivateKeyWithPassphrase([]byte(c.PrivateKey), []byte(c.PassPhrase))
|
|
||||||
} else {
|
|
||||||
signer, err = gossh.ParsePrivateKey([]byte(c.PrivateKey))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("NewClient parse private key => %s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config.Auth = []gossh.AuthMethod{gossh.PublicKeys(signer)}
|
|
||||||
} else {
|
|
||||||
config.Auth = []gossh.AuthMethod{gossh.Password(c.Password)}
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := gossh.Dial(proto, addr, config)
|
|
||||||
if nil != err {
|
|
||||||
logger.Errorf("NewClient dial => %s", err.Error())
|
|
||||||
return c, err
|
|
||||||
}
|
|
||||||
c.Client = client
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close 关闭当前SSH客户端
|
|
||||||
func (c *ConnSSH) Close() {
|
|
||||||
if c.Client != nil {
|
|
||||||
c.Client.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunCMD 执行单次命令
|
|
||||||
func (c *ConnSSH) RunCMD(cmd string) (string, error) {
|
|
||||||
if c.Client == nil {
|
|
||||||
if _, err := c.NewClient(); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
session, err := c.Client.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("RunCMD failed to create session: => %s", err.Error())
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer session.Close()
|
|
||||||
buf, err := session.CombinedOutput(cmd)
|
|
||||||
if err != nil {
|
|
||||||
logger.Infof("RunCMD failed run command: => %s", cmd)
|
|
||||||
logger.Errorf("RunCMD failed run command: => %s", err.Error())
|
|
||||||
}
|
|
||||||
c.LastResult = string(buf)
|
|
||||||
return c.LastResult, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientSession 创建SSH客户端会话对象
|
|
||||||
func (c *ConnSSH) NewClientSession(cols, rows int) (*SSHClientSession, error) {
|
|
||||||
sshSession, err := c.Client.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stdin, err := sshSession.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
comboWriter := new(singleWriter)
|
|
||||||
sshSession.Stdout = comboWriter
|
|
||||||
sshSession.Stderr = comboWriter
|
|
||||||
|
|
||||||
modes := gossh.TerminalModes{
|
|
||||||
gossh.ECHO: 1,
|
|
||||||
gossh.TTY_OP_ISPEED: 14400,
|
|
||||||
gossh.TTY_OP_OSPEED: 14400,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := sshSession.Shell(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SSHClientSession{
|
|
||||||
Stdin: stdin,
|
|
||||||
Stdout: comboWriter,
|
|
||||||
Session: sshSession,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientSFTP 创建SSH客户端SFTP对象
|
|
||||||
func (c *ConnSSH) NewClientSFTP() (*SSHClientSFTP, error) {
|
|
||||||
sftpClient, err := gosftp.NewClient(c.Client)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("NewClientSFTP failed to create sftp: => %s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &SSHClientSFTP{
|
|
||||||
Client: sftpClient,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClientByLocalPrivate 创建SSH客户端-本地私钥(~/.ssh/id_rsa)直连
|
|
||||||
//
|
|
||||||
// ssh.ConnSSH{
|
|
||||||
// User: "user",
|
|
||||||
// Addr: "192.168.x.x",
|
|
||||||
// Port: body.Port,
|
|
||||||
// }
|
|
||||||
func (c *ConnSSH) NewClientByLocalPrivate() (*ConnSSH, error) {
|
|
||||||
c.AuthMode = "1"
|
|
||||||
privateKey, err := c.CurrentUserRsaKey(false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.PrivateKey = privateKey
|
|
||||||
return c.NewClient()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentUserRsaKey 当前用户OMC使用的RSA私钥
|
|
||||||
// 默认读取私钥
|
|
||||||
// ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
|
|
||||||
// ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub
|
|
||||||
func (c *ConnSSH) CurrentUserRsaKey(publicKey bool) (string, error) {
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CurrentUserRsaKey get => %s", err.Error())
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 是否存在私钥并创建
|
|
||||||
keyPath := fmt.Sprintf("%s/.ssh/id_rsa", usr.HomeDir)
|
|
||||||
if _, err := os.Stat(keyPath); err != nil {
|
|
||||||
if _, err := cmd.ExecWithCheck("ssh-keygen", "-t", "rsa", "-P", "", "-f", keyPath); err != nil {
|
|
||||||
logger.Errorf("CurrentUserPrivateKey ssh-keygen [%s] rsa => %s", usr.Username, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取用户默认的文件
|
|
||||||
if publicKey {
|
|
||||||
keyPath = keyPath + ".pub"
|
|
||||||
}
|
|
||||||
key, err := os.ReadFile(keyPath)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("CurrentUserRsaKey [%s] read => %s", usr.Username, err.Error())
|
|
||||||
return "", fmt.Errorf("read file %s fail", keyPath)
|
|
||||||
}
|
|
||||||
return string(key), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SendToAuthorizedKeys 发送当前用户私钥到远程服务器进行授权密钥
|
|
||||||
func (c *ConnSSH) SendToAuthorizedKeys() error {
|
|
||||||
publicKey, err := c.CurrentUserRsaKey(true)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// "sudo mkdir -p ~/.ssh && sudo chown omcuser:omcuser ~/.ssh && sudo chmod 700 ~/.ssh"
|
|
||||||
// "sudo touch ~/.ssh/authorized_keys && sudo chown omcuser:omcuser ~/.ssh/authorized_keys && sudo chmod 600 ~/.ssh/authorized_keys"
|
|
||||||
// "echo 'ssh-rsa AAAAB3= pc-host\n' | sudo tee -a ~/.ssh/authorized_keys"
|
|
||||||
authorizedKeysEntry := fmt.Sprintln(strings.TrimSpace(publicKey))
|
|
||||||
cmdStrArr := []string{
|
|
||||||
fmt.Sprintf("sudo mkdir -p ~/.ssh && sudo chown %s:%s ~/.ssh && sudo chmod 700 ~/.ssh", c.User, c.User),
|
|
||||||
fmt.Sprintf("sudo touch ~/.ssh/authorized_keys && sudo chown %s:%s ~/.ssh/authorized_keys && sudo chmod 600 ~/.ssh/authorized_keys", c.User, c.User),
|
|
||||||
fmt.Sprintf("echo '%s' | sudo tee -a ~/.ssh/authorized_keys", authorizedKeysEntry),
|
|
||||||
}
|
|
||||||
_, err = c.RunCMD(strings.Join(cmdStrArr, " && "))
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("SendAuthorizedKeys echo err %s", err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package ssh
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
gossh "golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
// SSHClientSession SSH客户端会话对象
|
|
||||||
type SSHClientSession struct {
|
|
||||||
Stdin io.WriteCloser
|
|
||||||
Stdout *singleWriter
|
|
||||||
Session *gossh.Session
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close 关闭会话
|
|
||||||
func (s *SSHClientSession) Close() {
|
|
||||||
if s.Stdin != nil {
|
|
||||||
s.Stdin.Close()
|
|
||||||
}
|
|
||||||
if s.Stdout != nil {
|
|
||||||
s.Stdout = nil
|
|
||||||
}
|
|
||||||
if s.Session != nil {
|
|
||||||
s.Session.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write 写入命令 回车(\n)才会执行
|
|
||||||
func (s *SSHClientSession) Write(cmd string) (int, error) {
|
|
||||||
if s.Stdin == nil {
|
|
||||||
return 0, fmt.Errorf("ssh client session is nil to content write failed")
|
|
||||||
}
|
|
||||||
return s.Stdin.Write([]byte(cmd))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read 读取结果
|
|
||||||
func (s *SSHClientSession) Read() []byte {
|
|
||||||
if s.Stdout == nil {
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
bs := s.Stdout.Bytes()
|
|
||||||
if len(bs) > 0 {
|
|
||||||
s.Stdout.Reset()
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
return []byte{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// singleWriter SSH客户端会话消息
|
|
||||||
type singleWriter struct {
|
|
||||||
b bytes.Buffer
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *singleWriter) Write(p []byte) (int, error) {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
return w.b.Write(p)
|
|
||||||
}
|
|
||||||
func (w *singleWriter) Bytes() []byte {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
return w.b.Bytes()
|
|
||||||
}
|
|
||||||
func (w *singleWriter) Reset() {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
w.b.Reset()
|
|
||||||
}
|
|
||||||
@@ -15,8 +15,8 @@ import (
|
|||||||
"be.ems/src/framework/config"
|
"be.ems/src/framework/config"
|
||||||
"be.ems/src/framework/cron"
|
"be.ems/src/framework/cron"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/utils/crypto"
|
"be.ems/src/framework/utils/crypto"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
systemService "be.ems/src/modules/system/service"
|
systemService "be.ems/src/modules/system/service"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import (
|
|||||||
|
|
||||||
"be.ems/src/framework/database/redis"
|
"be.ems/src/framework/database/redis"
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/telnet"
|
"be.ems/src/framework/telnet"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/utils/parse"
|
"be.ems/src/framework/utils/parse"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
"be.ems/src/modules/network_element/model"
|
"be.ems/src/modules/network_element/model"
|
||||||
neService "be.ems/src/modules/network_element/service"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import (
|
|||||||
"be.ems/src/framework/constants/cachekey"
|
"be.ems/src/framework/constants/cachekey"
|
||||||
"be.ems/src/framework/database/redis"
|
"be.ems/src/framework/database/redis"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/telnet"
|
"be.ems/src/framework/telnet"
|
||||||
"be.ems/src/framework/utils/generate"
|
"be.ems/src/framework/utils/generate"
|
||||||
"be.ems/src/framework/utils/parse"
|
"be.ems/src/framework/utils/parse"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||||
"be.ems/src/modules/network_element/model"
|
"be.ems/src/modules/network_element/model"
|
||||||
"be.ems/src/modules/network_element/repository"
|
"be.ems/src/modules/network_element/repository"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
"be.ems/src/framework/config"
|
"be.ems/src/framework/config"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
"be.ems/src/framework/utils/ssh"
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
neService "be.ems/src/modules/network_element/service"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
wsModel "be.ems/src/modules/ws/model"
|
wsModel "be.ems/src/modules/ws/model"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
"be.ems/src/framework/utils/ssh"
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
neService "be.ems/src/modules/network_element/service"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
"be.ems/src/modules/tool/model"
|
"be.ems/src/modules/tool/model"
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/utils/date"
|
"be.ems/src/framework/utils/date"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
neFetchlink "be.ems/src/modules/network_element/fetch_link"
|
||||||
neModel "be.ems/src/modules/network_element/model"
|
neModel "be.ems/src/modules/network_element/model"
|
||||||
neService "be.ems/src/modules/network_element/service"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
"be.ems/src/framework/i18n"
|
"be.ems/src/framework/i18n"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/utils/ctx"
|
"be.ems/src/framework/utils/ctx"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
neService "be.ems/src/modules/network_element/service"
|
neService "be.ems/src/modules/network_element/service"
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
|
|
||||||
"be.ems/src/framework/database/redis"
|
"be.ems/src/framework/database/redis"
|
||||||
"be.ems/src/framework/logger"
|
"be.ems/src/framework/logger"
|
||||||
|
"be.ems/src/framework/ssh"
|
||||||
"be.ems/src/framework/telnet"
|
"be.ems/src/framework/telnet"
|
||||||
"be.ems/src/framework/utils/ssh"
|
|
||||||
"be.ems/src/framework/vo/result"
|
"be.ems/src/framework/vo/result"
|
||||||
"be.ems/src/modules/ws/model"
|
"be.ems/src/modules/ws/model"
|
||||||
"be.ems/src/modules/ws/processor"
|
"be.ems/src/modules/ws/processor"
|
||||||
|
|||||||
Reference in New Issue
Block a user