Go連接到Linux服務器進行操作
使用密碼連接Linux服務器
package main
import (
"fmt"
"golang.org/x/crypto/ssh"
"log"
"time"
)
func pwdConnect(sshHost, sshUser, sshPassword string, sshPort int) (*ssh.Client, error) {
// 創建ssh登錄配置
config := &ssh.ClientConfig{
Timeout: 5 * time.Second, // 超時時間
User: sshUser, // 登錄賬號
Auth: []ssh.AuthMethod{ssh.Password(sshPassword)}, // 密碼
HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 這個不夠安全,生產環境不建議使用
//HostKeyCallback: ssh.FixedHostKey(), // 建議使用這種,目前還沒研究出怎么使用[todo]
}
// dial連接服務器
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
Client, err := ssh.Dial("tcp", addr, config)
if err != nil {
log.Fatal("連接到服務器失敗", err)
return nil, err
}
//defer sshClient.Close()
return Client, nil
}
func main() {
// 連接到服務器
conn, err := pwdConnect("192.168.3.121", "root", "123456", 22)
if err != nil {
return
}
defer conn.Close()
// 創建 ssh session 會話
session, err := conn.NewSession()
if err != nil {
panic(err)
}
defer session.Close()
// 執行遠程命令
cmd := "cd /tmp/;ls -l; tar -czf test.tar.gz hello.txt test.txt;ls -l"
cmdInfo, err := session.CombinedOutput(cmd)
if err != nil {
panic(err)
}
fmt.Println(string(cmdInfo))
}
使用秘鑰連接到Linux服務器
package main
import (
"fmt"
"golang.org/x/crypto/ssh"
"io/ioutil"
"time"
)
// 使用秘鑰連接Linux服務器
// 連接到linux服務器
func keyConnect(sshUser, sshHost, sshKey string, sshPort int) (*ssh.Client, error) {
// 讀取秘鑰
key, err := ioutil.ReadFile(sshKey)
if err != nil {
panic("秘鑰讀取失敗")
}
// 創建秘鑰簽名
// 會拿着秘鑰去登錄服務器
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
panic("秘鑰簽名失敗")
}
// ssh配置
config := &ssh.ClientConfig{
Timeout: 5 * time.Second, // 超時時間
User: sshUser,
Auth: []ssh.AuthMethod{
// 使用秘鑰登錄遠程服務器
ssh.PublicKeys(signer),
},
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //這個不夠安全,生產環境不建議使用
//var hostKey ssh.PublicKey
//HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// 連接遠程服務器
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
client, err := ssh.Dial("tcp", addr, config)
if err != nil {
fmt.Println("連接遠程服務器失敗", err)
return nil, err
}
//defer client.Close()
return client, nil
}
func main() {
// 連接服務器
conn, err := keyConnect("root", "192.168.3.121", "id_rsa", 22)
if err != nil {
panic(err)
}
defer conn.Close()
// 創建 ssh session 會話
session, err := conn.NewSession()
if err != nil {
panic(err)
}
defer session.Close()
// 執行遠程命令
cmd := "cd /tmp/; ls -l"
cmdInfo, err := session.CombinedOutput(cmd)
if err != nil {
panic(err)
}
fmt.Println(string(cmdInfo))
}
使用秘鑰或者密碼連接到服務器
package main
import (
"errors"
"fmt"
"golang.org/x/crypto/ssh"
"io/ioutil"
"log"
"time"
)
func keyOrPwdConnect(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*ssh.Client, error) {
// 創建ssh登錄配置
config := &ssh.ClientConfig{
Timeout: 5 * time.Second, // 超時時間
User: sshUser, // 登錄賬號
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //這個不夠安全,生產環境不建議使用
//HostKeyCallback: ssh.FixedHostKey(), //建議使用這種
}
if sshKey != "" {
// 秘鑰登錄
key, err := ioutil.ReadFile(sshKey) // 讀取秘鑰
if err != nil {
panic("秘鑰讀取失敗")
}
// 創建秘鑰簽名
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
panic("秘鑰簽名失敗")
}
// 配置秘鑰登錄
config.Auth = []ssh.AuthMethod{
ssh.PublicKeys(signer),
}
} else if sshPassword != "" {
// 密碼登錄
config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
} else {
err := errors.New("秘鑰或者密碼登錄")
return nil, err
}
// dial連接服務器
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
Client, err := ssh.Dial("tcp", addr, config)
if err != nil {
log.Fatal("連接到服務器失敗", err)
return nil, err
}
return Client, nil
}
func main() {
// 連接服務器
//conn, err := keyOrPwdConnect("192.168.3.121", "root", "", "id_rsa", 22) // 秘鑰登錄
conn, err := keyOrPwdConnect("192.168.3.121", "root", "123456", "", 22) // 密碼登錄
if err != nil {
panic(err)
}
defer conn.Close()
// 創建 ssh session 會話
session, err := conn.NewSession()
if err != nil {
panic(err)
}
defer session.Close()
// 執行遠程命令
cmd := "echo 'hello world!'"
cmdInfo, err := session.CombinedOutput(cmd)
if err != nil {
panic(err)
}
fmt.Println(string(cmdInfo))
}
上傳文件到Linux服務器
package main
import (
"errors"
"fmt"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"io/ioutil"
"log"
"os"
"path"
"time"
)
// 通過SSH連接Linux服務器
func keyOrPwdConnectLinuxServer(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*ssh.Client, error) {
// 創建ssh登錄配置
config := &ssh.ClientConfig{
Timeout: 5 * time.Second, // 超時時間
User: sshUser, // 登錄賬號
HostKeyCallback: ssh.InsecureIgnoreHostKey(), //這個不夠安全,生產環境不建議使用
//HostKeyCallback: ssh.FixedHostKey(), //建議使用這種
}
if sshKey != "" {
// 秘鑰登錄
key, err := ioutil.ReadFile(sshKey)
if err != nil {
panic("秘鑰讀取失敗")
}
// 創建秘鑰簽名
// 會拿着秘鑰去登錄服務器
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
panic("秘鑰簽名失敗")
}
// 配置秘鑰登錄
config.Auth = []ssh.AuthMethod{
ssh.PublicKeys(signer),
}
} else if sshPassword != "" {
// 密碼登錄
config.Auth = []ssh.AuthMethod{ssh.Password(sshPassword)}
} else {
err := errors.New("秘鑰或者密碼登錄")
return nil, err
}
// dial連接服務器
addr := fmt.Sprintf("%s:%d", sshHost, sshPort)
Client, err := ssh.Dial("tcp", addr, config)
if err != nil {
log.Fatal("連接到服務器失敗", err)
return nil, err
}
return Client, nil
}
// 創建sftp會話
func CreateSftp(sshHost, sshUser, sshPassword, sshKey string, sshPort int) (*sftp.Client, error) {
// 連接Linux服務器
conn, err := keyOrPwdConnectLinuxServer(sshHost, sshUser, sshPassword, sshKey, sshPort)
if err != nil {
fmt.Println("連接Linux服務器失敗")
panic(err)
}
//defer conn.Close()
// 創建sftp會話
client, err := sftp.NewClient(conn)
if err != nil {
return nil, err
}
//defer client.Close()
return client, nil
}
func main() {
// 連接sftp
client, err := CreateSftp("192.168.3.121", "root", "123456", "", 22)
if err != nil {
return
}
defer client.Close()
// 瀏覽服務器/home/devel目錄
//w := client.Walk("/home/devel")
//for w.Step() {
// if w.Err() != nil {
// continue
// }
// fmt.Println(w.Path())
//}
// 在服務器創建文件
//f, err := client.Create("/tmp/hello.txt")
//if err != nil {
// panic(err)
//}
//_, err = f.Write([]byte("hello world!\n")) // 寫入內容
//if err != nil {
// panic(err)
//}
//f.Close()
// 查看服務器的文件
//fi, err := client.Lstat("/tmp/hello.txt")
//if err != nil {
// panic(err)
//}
//fmt.Printf("%#v\n", fi)
// 上傳文件
var localFilePath = "./test.txt" // 本地文件全路徑
var remoteDir = "/tmp" // 服務器目錄
// 打開需要上傳的本地文件
srcFile, err := os.Open(localFilePath)
if err != nil {
panic(err)
}
defer srcFile.Close()
// 獲取需要上傳的文件的名稱
var remoteFileName = path.Base(localFilePath)
// 在服務器創建文件並打開文件獲得句柄
dstFile, err := client.Create(path.Join(remoteDir, remoteFileName))
if err != nil {
panic(err)
}
defer dstFile.Close()
// 寫入內容
buf := make([]byte, 1024)
for {
n, _ := srcFile.Read(buf) // 把文件中的內容讀取到buf中,每次讀取本地需要上傳的文件1024字節內容
// 當n=0時,證明本地需要上傳的文件已經讀取完畢了
if n == 0 {
break
}
dstFile.Write(buf) // 寫入到句柄
}
fmt.Println("文件上傳完畢")
}