使用Python无密钥自动执行多个SCP传输

时间:2012-07-27 16:56:27

标签: python ssh automation scp

我需要在使用自动非交互式python脚本编译后,将两个程序从一个服务器复制到另一个服务器。密钥不是一个选项,因为此脚本适用于公司服务器上的多个用户,并且需要密钥和密码。密码不会存储在程序中,但会在程序开始时使用getpass()询问一次,然后用于两次SCP传输,这样用户就不必为每个scp调用输入密码。我正在使用os.system来调用scp:

os.system("/usr/bin/scp %s %s@server:directory" %(prg, uname))
os.system("/usr/bin/scp %s %s@server:directory2" %(prg2, uname))

scp是为另一个程序定义的,因此是/ usr / bin / scp。 prg / prg2是程序的位置,uname是远程服务器上的用户用户名。

我试过管道密码,比如described here,但它不起作用。

我无法安装sshpass,expect,paramiko或fabric,我不能使用rsync b / c它没有安装在接收服务器上。我能做些什么来实现自动化吗?

我正在运行AIX 6.1,Python 2.6.2

更新:我无法安装外部库,例如pexpect,因为AIX在python安装目录中没有/ config文件夹。解决这个问题的方法是安装python-devel for AIX,但是我无法安装程序,所以我仍然卡住了。

更新2:我决定放弃SCP而支持FTP。我使用thisthis的组合来制作我的FTP脚本。感谢您的回答并帮助指导我。

2 个答案:

答案 0 :(得分:2)

由于您必须在没有安装权限的纯Python中实现此功能, 你要重新发明轮子,它很糟糕。在这种情况下你需要什么 是SSH_ASKPASS漏洞。

SSH真的不希望你只是给它一个密码 - 毕竟,那是什么 密钥文件用于。但是,如果设置了SSH_ASKPASS环境变量, 设置了DISPLAY环境变量, ssh没有在里面运行 一个TTY,它将执行ASKPASS程序(同时保持其环境 调用ASKPASS程序的上下文中的变量。作为一个 结果,如果你很聪明,你可以设置一个回声程序作为你的 ASKPASS和强制ssh以你想要的方式做你想做的事。

以下是我见过的代码片段 - 事实并非如此 完成(它从一个模块的中间抬起),但它应该得到你 开始。我们使用base64在这个密码上放了一个遮羞布。

def createConnection(self, hostName, username, password):
    """ Because we're setting both stdout and stderr to be pipes, we have
        to worry about one of them clogging - We'll be reading stdout
        constantly through the code, but stderr needs a worker to handle
        it. """

    env = {'SSH_ASKPASS': '/path/to/echo/script',
           'DISPLAY': 'required',
           'ENCODED_PASSWORD': base64.b64encode(password)}
    self.username = username
    self.hostName = hostName
    self.sshProcess = subprocess.Popen(
        ['/usr/bin/ssh', '-T',
         '-o', 'UserKnownHostsFile=/dev/null',
         '-o', 'StrictHostKeyChecking=no',
         '-o', 'NumberOfPasswordPrompts=1',
         '-o', 'ConnectTimeout=10',
         '%s@%s' % (username, hostName),
         '-s', 'xmlagent',
        ],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env,

        #this kicks it out of the controlling tty session
        preexec_fn=os.setsid
    )

    self.sshStderr = ''
    self.errorThread = threading.Thread(target=self.readStderr)
    self.errorThread.daemon = True
    self.errorThread.start()

答案 1 :(得分:1)

您需要使用pexpect

使用示例(来自Automate SSH without using public key authentication or expect(1)):

import pexpect

FILE="/path/to/file"
REMOTE_FILE=""
USER="user"
HOST="example.com"
PASS="mypass"
COMMAND="scp -oPubKeyAuthentication=no %s %s@%s:%s" % (FILE, USER, HOST, REMOTE_FILE)

child = pexpect.spawn(COMMAND)
child.expect('password:')
child.sendline(PASS)
child.expect(pexpect.EOF)
print child.before

您也可以尝试expect(然后从python运行脚本;如果您无法安装pexpect,这是一个很好的解决方案:

#!/usr/bin/expect -f
set filename [lindex $argv 0]
set timeout -1
spawn scp $filename myusername@192.168.1.123:/home/myusername/
set pass "mypassword"
expect {
         password: {send "$pass\r" ; exp_continue}
         eof exit
}