我需要在使用自动非交互式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,但是我无法安装程序,所以我仍然卡住了。
答案 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
}