我正在做一个Python脚本,我需要生成几个ssh-copy-id进程,他们需要输入密码,所以我使用的是PExpect。
基本上我有这个:
child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')
然后我想生成另一个进程,我不再关心这个进程,无论结束与否。
child = pexpect.spawn('command2')
child.expect('password:')
child.sendline('the password')
代码挂在第二个“spawn”
但是,如果我注释掉第一个电话,第二个电话会工作,所以我猜测第一个电话仍然在运行,或者有什么东西阻止它工作。
现在,我无法做的另一件事是等到第一个停止。
我试过了:
child.close() - 它挂起(以True和False作为参数)
child.read(-1) - 它挂起了
child.expect(pexpect.EOF) - 它挂起。
child.terminate() - 它挂起(以True和False作为参数)
关于可能发生的事情的任何想法?
注意:我不是Python专家,之前从未使用过pexpect,所以任何想法都非常受欢迎。
谢谢!
更新:这肯定与ssh-copy-id有关,因为对于其他进程,即使它们不返回,spawn也能正常工作。 此外,显然ssh-copy-id永远不会返回EOF。
答案 0 :(得分:3)
幸运与否,但OpenSSH客户端似乎对密码及其来源非常挑剔。
您可以尝试使用Paramiko Python SSH2库。这是一个简单的example how to use it with password authentication,然后发出一些shell命令(echo "..." >> $HOME/.ssh/authorized_keys
是最简单的)来在远程主机上添加你的公钥。
答案 1 :(得分:1)
我认为问题是,SSH试图打开PTY而它不起作用 出于安全原因,除了PTY之外的任何事情。这不会很好 与pexpect。
我有另一个ssh客户端:
它是开源的,你可以使用它。你想要做的是什么 更多的命令,但你根本不需要期望。
首先将其安装到手册中,然后执行以下操作:
运行dssh-agent,添加您需要的密码:
dssh-add -l < passwordfile
或者如果它是安全的机器,即没有其他人可以登录, 这非常很重要,否则这将是一个巨大的安全漏洞:
echo "name-of-server;22;root;password;" | dssh-add -l
password
文件类似于:
name-of-server;22;root;password;
并执行类似操作(将CONTENTS OF ...
替换为该文件的实际内容):
dssh root@name-of-server -- echo "CONTENTS OF ~/.ssh/identity.pub" > .ssh/authorized_keys \; chmod og-w .ssh .ssh/authorized_keys
您可以(可选)执行
dssh-add -f passwords
(确保没有其他人在做所有这些事情,否则你会这样做 有竞争条件)。
此外,pexpect应该可以与dssh本身一起使用(所以你不需要 使用dssh-agent)。但是使用dssh-agent更简单,更安全。
DSSH的安装手册包含在tarball中。
我不知道这样做的简单方法,OpenSSH ssh-copy-id是 非常挑剔密码的来源......
答案 2 :(得分:0)
阅读pexpect documentation for spawn,我认为它正在等待命令终止。
根据您的需要,我会建议几种不同的可能性:
1)杀死衍生过程。但是,这可能会导致您的操作损坏,所以我不知道它是否是您想要的。
child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')
child.close(True)
2)等待完成初始任务,然后再转到下一个
child = pexpect.spawn('command')
child.expect('password:')
child.sendline('the password')
child.wait()
child = pexpect.spawn('command2')
...
3)为所有孩子使用不同的实例,然后在最后等待所有孩子 - 这很可能是最好的解决方案
def exec_command(cmd):
child = pexpect.spawn(cmd)
child.expect('password:')
child.sendline('the password')
return child
commands = ['command1', 'command2']
childrens = [exec_command(cmd) for cmd in commands]
for child in childrens:
child.wait()
注意:这里的所有代码都是未经测试的,并且假设您的脚本处于挂起状态而编写,因为删除spawn对象将会挂起,直到命令终止。
答案 3 :(得分:0)
实际上,我尝试了很多这些替代方案,但都没有奏效。
我用其他命令(比如'ftp')进行了一些测试,并且它们按照我的预期工作,例如,如果你调用.expect('某事'),并且在EOF之前找不到某些东西,他们不会t等待永远,他们抛出异常,所以我相信这与ssh-copy-id命令有关。