13

scpを使用して(セキュアコピー)コマンドを実行しようとしていsubprocess.Popenます。ログインするには、パスワードを送信する必要があります。

from subprocess import Popen, PIPE

proc = Popen(['scp', "user@10.0.1.12:/foo/bar/somefile.txt", "."], stdin = PIPE)
proc.stdin.write(b'mypassword')
proc.stdin.flush()

これはすぐにエラーを返します:

user@10.0.1.12's password:
Permission denied, please try again.

パスワードは正しいと確信しています。scpシェルを手動で呼び出すことで簡単に確認できます。では、なぜこれが機能しないのですか?

subprocess.Popenこれに似た質問がたくさんあることに注意してください。自動SSHまたはFTPログインのパスワードを尋ねて送信します。

LinuxでPythonスクリプトからユーザーパスワードを設定するにはどうすればよいですか?
サブプロセスを使用してパスワードを送信する

Python 3を使用しているため、これらの質問に対する回答が機能しないか、適用されません。

4

6 に答える 6

12

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 %s@%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です。

于 2013-03-01T22:05:24.687 に答える
7

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

于 2013-03-01T21:28:39.920 に答える
1

一部のアプリケーションは stdin を使用してユーザーとやり取りし、一部のアプリケーションは端末を使用してやり取りすると思います。この場合、PIPE を使用してパスワードを書き込むときは、stdin に書き込みます。ただし、SCP アプリケーションは端末からパスワードを読み取ります。サブプロセスはターミナルを使用してユーザーと対話することはできませんが、stdin を使用してのみ対話できるため、サブプロセス モジュールを使用することはできず、scp を使用してファイルをコピーするには pexpect を使用する必要があります。

修正はお気軽に。

于 2017-10-04T12:01:26.040 に答える
0

これは、pexpect に基づく私の scp 関数です。パスワードに加えて、ワイルドカード (つまり、複数のファイル転送) を処理できます。複数のファイル転送 (つまり、ワイルドカード) を処理するには、シェル経由でコマンドを発行する必要があります。pexpect FAQを参照してください。

import pexpect

def scp(src,user2,host2,tgt,pwd,opts='',timeout=30):
    ''' Performs the scp command. Transfers file(s) from local host to remote host '''
    cmd = f'''/bin/bash -c "scp {opts} {src} {user2}@{host2}:{tgt}"'''
    print("Executing the following cmd:",cmd,sep='\n')

    tmpFl = '/tmp/scp.log'
    fp = open(tmpFl,'wb')
    childP = pexpect.spawn(cmd,timeout=timeout)
    try:
        childP.sendline(cmd)
        childP.expect([f"{user2}@{host2}'s password:"])
        childP.sendline(pwd)
        childP.logfile = fp
        childP.expect(pexpect.EOF)
        childP.close()
        fp.close()

        fp = open(tmpFl,'r')
        stdout = fp.read()
        fp.close()

        if childP.exitstatus != 0:
            raise Exception(stdout)
    except KeyboardInterrupt:
        childP.close()
        fp.close()
        return

    print(stdout)

次のように使用できます。

params = {
    'src': '/home/src/*.txt',
    'user2': 'userName',
    'host2': '192.168.1.300',
    'tgt': '/home/userName/',
    'pwd': myPwd(),
    'opts': '',
}

scp(**params)
于 2019-04-26T02:59:04.533 に答える