0

在使用自动非交互式 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 是远程服务器上的用户名。

我尝试使用管道输入密码,如此处所述,但它不起作用。

我无法安装 sshpass、expect、paramiko 或 fabric,也无法使用未安装在接收服务器上的 rsync b/c。我能做些什么来自动化这个吗?

我正在运行 AIX 6.1、Python 2.6.2

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

更新 2:我决定放弃 SCP 以支持 FTP。我结合使用了这个这个来制作我的 FTP 脚本。感谢您的回答和帮助指导我。

4

2 回答 2

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()
于 2012-07-27T22:54:58.770 回答
1

你需要使用pexpect.

使用示例(来自Automate SSH without using public key authentication 或 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
}
于 2012-07-27T16:58:49.600 回答