GNU/Linux >> Linux の 問題 >  >> Linux

subprocess.Popen を使用して SSH または SCP 経由でパスワードを送信する

OpenSSH scp ユーティリティは ssh を呼び出します リモート ホストへの SSH 接続を確立するプログラムと、ssh プロセスが認証を処理します。 ssh utility は、コマンド ラインまたはその標準入力でパスワードを受け入れません。これは OpenSSH 開発者側の意図的な決定だと思います。なぜなら、人々は鍵ベースの認証のようなより安全なメカニズムを使用すべきだと感じているからです。 ssh を呼び出すためのソリューションは、次のいずれかのアプローチに従います:

<オール>
  • 認証にパスワードの代わりに SSH キーを使用する
  • sshpass、expect、または同様のツールを使用して、パスワード プロンプトへの応答を自動化します。
  • SSH_ASKPASS 機能を使用 (悪用) して ssh を取得する ここまたはここ、またはここの回答のいくつかで説明されている別のコマンドを呼び出して、パスワードを取得します。
  • SSH サーバー管理者にホストベースの認証を有効にしてもらい、それを使用してもらいます。ホストベースの認証は、特定のネットワーク環境にのみ適していることに注意してください。こちらとこちらの追加メモをご覧ください。
  • perl、python、java、または好みの言語を使用して独自の ssh クライアントを作成します。最新のほとんどのプログラミング言語で使用できる ssh クライアント ライブラリがあり、クライアントがパスワードを取得する方法を完全に制御できます。
  • ssh ソース コードをダウンロードし、ssh の修正バージョンをビルドします。 思い通りに機能します。
  • 別の ssh クライアントを使用します。無料と商用の両方で利用可能な他の ssh クライアントがあります。そのうちの 1 つは、OpenSSH クライアントよりもニーズに適している場合があります。
  • この特定のケースでは、すでに scp を呼び出していることを考えると、 Python スクリプトから、これらの 1 つが最も合理的なアプローチのようです:

    <オール>
  • Python の Expect モジュールである pexpect を使用して、scp を呼び出します。 それにパスワードを入力してください。
  • 外部プログラムを呼び出す代わりに、python ssh 実装である paramiko を使用して、この ssh タスクを実行します。

  • ssh への関数は次のとおりです。 pexpect を使用したパスワード :

    import pexpect
    import tempfile
    
    def ssh(host, cmd, user, password, timeout=30, bg_run=False):                                                                                                 
        """SSH'es to a host using the supplied credentials and executes a command.                                                                                                 
        Throws an exception if the command doesn't return 0.                                                                                                                       
        bgrun: run command in the background"""                                                                                                                                    
                                                                                                                                                                                   
        fname = tempfile.mktemp()                                                                                                                                                  
        fout = open(fname, 'w')                                                                                                                                                    
                                                                                                                                                                                   
        options = '-q -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -oPubkeyAuthentication=no'                                                                         
        if bg_run:                                                                                                                                                         
            options += ' -f'                                                                                                                                                       
        ssh_cmd = 'ssh %[email protected]%s %s "%s"' % (user, host, options, cmd)                                                                                                                 
        child = pexpect.spawn(ssh_cmd, timeout=timeout)  #spawnu for Python 3                                                                                                                          
        child.expect(['[pP]assword: '])                                                                                                                                                                                                                                                                                               
        child.sendline(password)                                                                                                                                                   
        child.logfile = fout                                                                                                                                                       
        child.expect(pexpect.EOF)                                                                                                                                                  
        child.close()                                                                                                                                                              
        fout.close()                                                                                                                                                               
                                                                                                                                                                                                                                                                                                                            
        fin = open(fname, 'r')                                                                                                                                                     
        stdout = fin.read()                                                                                                                                                        
        fin.close()                                                                                                                                                                
                                                                                                                                                                                   
        if 0 != child.exitstatus:                                                                                                                                                  
            raise Exception(stdout)                                                                                                                                                
                                                                                                                                                                                   
        return stdout
    

    scp を使用して同様のことが可能になるはずです .


    リンクした2番目の回答は、Pexpectを使用することを示唆しています(これは通常、入力を必要とするコマンドラインプログラムと対話するための正しい方法です)。使用できる python3 で動作するフォークがあります。


    Linux
    1. UNIX / Linux で SSH を使用して Rsync をセットアップする方法 (パスワードなしの rsync)

    2. Linux で空のパスワードで ssh を許可する方法

    3. ssh経由でLinuxサーバーのパスワードを変更するスクリプト

    1. 暗号化されたホームディレクトリを持つUbuntuシステムへのauthorized_keysを使用したSSH?

    2. UNIX / Linux で SSH を使用してパスワードなしで Rsync をセットアップする方法は?

    3. リモートパスワードの入力を求める SSH による Rsync

    1. パラメータとしてクリアテキストパスワードを使用したSSHログイン??

    2. 転送された ssh エージェントで scp を使用する

    3. sshfs を使用したコマンドラインでのユーザー名とパスワード