golang を使用して ssh をカプセル化し、リモート ホスト上でコマンドを実行し、ファイルをアップロードまたはダウンロードする方法について
次の golang のチュートリアル コラムでは、golang を使用して ssh をカプセル化し、リモート ホスト上でコマンドを実行し、ファイルをアップロードまたはダウンロードする方法を紹介します。それを必要としている友達の役に立つでしょう。役に立ちました!
Python では、paramiko を使用してコマンドを実行し、リモート ホスト上でファイルをアップロードおよびダウンロードできます。go でカプセル化することもできます。go では ssh を使用できます次の関数が実装されています。
- リモート ホスト上でコマンドを実行して、結果、戻り値を返します。
- リモート ホスト上でファイルをアップロードおよびダウンロードします。および転送されるバイト数
認証方法
- #パスワードが指定されている場合は、ユーザーのパスワードが認証に使用され、それ以外の場合はユーザーのシークレットが使用されます。キーは認証に使用されます。
- ユーザーが指定されていない場合、デフォルトで現在のユーザーが使用されます。
- パスワードが指定されていない場合は、ユーザー キー方式が使用されます。秘密キーを取得するには、デフォルトで ~/.ssh/id_rsa ファイルの秘密キー ファイルが取得されます。
paramik と同様です。
コードを直接アップロードします。
package mainimport ( "errors" "fmt" "github.com/pkg/sftp" "golang.org/x/crypto/ssh" "io" "io/ioutil" "log" "os" "os/user" "time")var ( DefaultSShTcpTimeout = 15 * time.Second // 与ssh建立连接的默认时间,自己设置一个就行)// 错误定义var ( InvalidHostName = errors.New("invalid parameters: hostname is empty") InvalidPort = errors.New("invalid parameters: port must be range 0 ~ 65535"))// 返回当前用户名func getCurrentUser() string { user, _ := user.Current() return user.Username}// 存放上传或下载的信息type TransferInfo struct { Kind string // upload或download Local string // 本地路径 Dst string // 目标路径 TransferByte int64 // 传输的字节数(byte)}func (t *TransferInfo) String() string { return fmt.Sprintf(`TransforInfo(Kind:"%s", Local: "%s", Dst: "%s", TransferByte: %d)`, t.Kind, t.Local, t.Dst, t.TransferByte)}// 存放执行结果的结构体信息type ExecInfo struct { Cmd string Output []byte ExitCode int}func (e *ExecInfo) OutputString() string { return string(e.Output)}func (e *ExecInfo) String() string { return fmt.Sprintf(`ExecInfo(cmd: "%s", exitcode: %d)`, e.Cmd, e.ExitCode)}type AuthConfig struct { *ssh.ClientConfig User string Password string KeyFile string Timeout time.Duration}func (a *AuthConfig) setDefault() { if a.User == "" { a.User = getCurrentUser() } if a.KeyFile == "" { userHome, _ := os.UserHomeDir() a.KeyFile = fmt.Sprintf("%s/.ssh/id_rsa", userHome) } if a.Timeout == 0 { a.Timeout = DefaultSShTcpTimeout }}func (a *AuthConfig) SetAuthMethod() (ssh.AuthMethod, error) { a.setDefault() if a.Password != "" { return ssh.Password(a.Password), nil } data, err := ioutil.ReadFile(a.KeyFile) if err != nil { return nil, err } singer, err := ssh.ParsePrivateKey(data) if err != nil { return nil, err } return ssh.PublicKeys(singer), nil}func (a *AuthConfig) ApplyConfig() error { authMethod, err := a.SetAuthMethod() if err != nil { return err } a.ClientConfig = &ssh.ClientConfig{ User: a.User, Auth: []ssh.AuthMethod{authMethod}, HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: a.Timeout, } return nil}// 存放连接的结构体type conn struct { client *ssh.Client sftpClient *sftp.Client}func (c *conn) Close() { if c.sftpClient != nil { c.sftpClient.Close() c.sftpClient = nil } if c.client != nil { c.client.Close() c.client = nil }}// SSHClient结构体type SSHClient struct { conn HostName string Port int AuthConfig AuthConfig}// 设置默认端口信息func (s *SSHClient) setDefaultValue() { if s.Port == 0 { s.Port = 22 }}// 与远程主机连接func (s *SSHClient) Connect() error { if s.client != nil { log.Println("Already Login") return nil } if err := s.AuthConfig.ApplyConfig(); err != nil { return err } s.setDefaultValue() addr := fmt.Sprintf("%s:%d", s.HostName, s.Port) var err error s.client, err = ssh.Dial("tcp", addr, s.AuthConfig.ClientConfig) if err != nil { return err } return nil}// 一个session只能执行一次命令,也就是说不能在同一个session执行多次s.session.CombinedOutput// 如果想执行多次,需要每条为每个命令创建一个session(这里是这样做)func (s *SSHClient) Exec(cmd string) (*ExecInfo, error) { session, err := s.client.NewSession() if err != nil { return nil, err } defer session.Close() output, err := session.CombinedOutput(cmd) var exitcode int if err != nil { // 断言转成具体实现类型,获取返回值 exitcode = err.(*ssh.ExitError).ExitStatus() } return &ExecInfo{ Cmd: cmd, Output: output, ExitCode: exitcode, }, nil}// 将本地文件上传到远程主机上func (s *SSHClient) Upload(localPath string, dstPath string) (*TransferInfo, error) { transferInfo := &TransferInfo{Kind: "upload", Local: localPath, Dst: dstPath, TransferByte: 0} var err error // 如果sftp客户端没有打开,就打开,为了复用 if s.sftpClient == nil { if s.sftpClient, err = sftp.NewClient(s.client); err != nil { return transferInfo, err } } localFileObj, err := os.Open(localPath) if err != nil { return transferInfo, err } defer localFileObj.Close() dstFileObj, err := s.sftpClient.Create(dstPath) if err != nil { return transferInfo, err } defer dstFileObj.Close() written, err := io.Copy(dstFileObj, localFileObj) if err != nil { return transferInfo, err } transferInfo.TransferByte = written return transferInfo, nil}// 从远程主机上下载文件到本地func (s *SSHClient) Download(dstPath string, localPath string) (*TransferInfo, error) { transferInfo := &TransferInfo{Kind: "download", Local: localPath, Dst: dstPath, TransferByte: 0} var err error if s.sftpClient == nil { if s.sftpClient, err = sftp.NewClient(s.client); err != nil { return transferInfo, err } } //defer s.sftpClient.Close() localFileObj, err := os.Create(localPath) if err != nil { return transferInfo, err } defer localFileObj.Close() dstFileObj, err := s.sftpClient.Open(dstPath) if err != nil { return transferInfo, err } defer dstFileObj.Close() written, err := io.Copy(localFileObj, dstFileObj) if err != nil { return transferInfo, err } transferInfo.TransferByte = written return transferInfo, nil}// SSHclient的构造方法func NewSSHClient(hostname string, port int, authConfig AuthConfig) (*SSHClient, error) { switch { case hostname == "": return nil, InvalidHostName case port > 65535 || port < 0: return nil, InvalidPort } sshClient := &SSHClient{HostName: hostname, Port: port, AuthConfig: authConfig} err := sshClient.Connect() if err != nil { return nil, err } return sshClient, nil}func main() {// 测试 sshClient, err := NewSSHClient("172.16.0.178", 22, AuthConfig{User: "root"}) if err != nil { fmt.Println(err) return } defer sshClient.Close() //第一次 执行命令 execinfo, err := sshClient.Exec("ls -l") fmt.Println(execinfo.OutputString(), err) //第二次执行命令 out1, exitcode2 := sshClient.Exec("ifconfig -a") fmt.Println(string(out1), exitcode2) // 上传文件 transInfoUpload, err := sshClient.Upload("/tmp/passwd", "/tmp/password_upload") fmt.Println(transInfoUpload, err) // 下载文件 transInfoDownload, err := sshClient.Download("/etc/passwd", "/tmp/passwd_download") fmt.Println(transInfoDownload, err)}
以上がgolang を使用して ssh をカプセル化し、リモート ホスト上でコマンドを実行し、ファイルをアップロードまたはダウンロードする方法についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Go ではファイルを安全に読み書きすることが重要です。ガイドラインには以下が含まれます。 ファイル権限の確認 遅延を使用してファイルを閉じる ファイル パスの検証 コンテキスト タイムアウトの使用 これらのガイドラインに従うことで、データのセキュリティとアプリケーションの堅牢性が確保されます。

Go データベース接続の接続プーリングを構成するにはどうすればよいですか?データベース接続を作成するには、database/sql パッケージの DB タイプを使用します。同時接続の最大数を制御するには、MaxOpenConns を設定します。アイドル状態の接続の最大数を設定するには、ConnMaxLifetime を設定します。

Go フレームワークは、その高いパフォーマンスと同時実行性の利点で際立っていますが、比較的新しい、開発者エコシステムが小さい、一部の機能が欠けているなどの欠点もあります。さらに、急速な変化と学習曲線はフレームワークごとに異なる場合があります。 Gin フレームワークは、効率的なルーティング、組み込みの JSON サポート、強力なエラー処理機能により、RESTful API を構築するための一般的な選択肢です。

GoLang フレームワークと Go フレームワークの違いは、内部アーキテクチャと外部機能に反映されています。 GoLang フレームワークは Go 標準ライブラリに基づいてその機能を拡張していますが、Go フレームワークは特定の目的を達成するための独立したライブラリで構成されています。 GoLang フレームワークはより柔軟であり、Go フレームワークは使いやすいです。 GoLang フレームワークはパフォーマンスの点でわずかに優れており、Go フレームワークはよりスケーラブルです。ケース: gin-gonic (Go フレームワーク) は REST API の構築に使用され、Echo (GoLang フレームワーク) は Web アプリケーションの構築に使用されます。

JSON データは、gjson ライブラリまたは json.Unmarshal 関数を使用して MySQL データベースに保存できます。 gjson ライブラリは、JSON フィールドを解析するための便利なメソッドを提供します。json.Unmarshal 関数には、JSON データをアンマーシャリングするためのターゲット型ポインターが必要です。どちらの方法でも、SQL ステートメントを準備し、データをデータベースに永続化するために挿入操作を実行する必要があります。

ベスト プラクティス: 明確に定義されたエラー タイプ (エラー パッケージ) を使用してカスタム エラーを作成する 詳細を提供する エラーを適切にログに記録する エラーを正しく伝播し、非表示または抑制しないようにする コンテキストを追加するために必要に応じてエラーをラップする

FindStringSubmatch 関数は、正規表現に一致する最初の部分文字列を検索します。この関数は、最初の要素が一致した文字列全体で、後続の要素が個々の部分文字列である、一致する部分文字列を含むスライスを返します。コード例: regexp.FindStringSubmatch(text,pattern) は、一致する部分文字列のスライスを返します。実際のケース: 電子メール アドレスのドメイン名を照合するために使用できます。たとえば、email:="user@example.com", pattern:=@([^\s]+)$ を使用してドメイン名を照合します。 [1]。

バックエンド学習パス:フロントエンドからバックエンドへの探査の旅は、フロントエンド開発から変わるバックエンド初心者として、すでにNodeJSの基盤を持っています...
