Pexpect,试图产生第二个进程时运行ssh-copy-id

问题描述:

我在做一个Python脚本,我需要产生几个ssh-copy-id进程,他们需要输入密码,所以我使用PExpect。Pexpect,试图产生第二个进程时运行ssh-copy-id

我基本上是这样的:

child = pexpect.spawn('command') 
child.expect('password:') 
child.sendline('the password') 

,然后我想产生另一个过程,我不关心这个了,无论是结束。

child = pexpect.spawn('command2') 
child.expect('password:') 
child.sendline('the password') 

和代码在第二个“重生”是挂

但是,如果我注释掉第一个呼叫,第二个作品,所以我猜这个事实,第一个是仍然在运行或者不能正常工作。

现在,我无法做的另一件事是等到第一个停下来。 我已经试过:
child.close() - 它挂起(包括真假作为参数) child.read(-1) - 它挂
child.expect(pexpect.EOF) - 它挂起。
child.terminate() - 挂起(以True和False作为参数)

有关可能发生什么的任何想法?
注意:我不是Python专家,我以前从未使用过pexpect,所以任何想法都是值得欢迎的。

谢谢!


UPDATE:这是肯定有关的ssh-copy-id命令,因为与其他进程,产卵效果很好,即使他们不返回。 此外,显然ssh-copy-id永远不会返回EOF。

+1

@DanialMagliola你有任何完美的解决方案吗? – Nilesh 2011-12-21 10:31:57

+0

以下是来自http://linux.byexamples.com/archives/346/python-how-to-access-ssh-with-pexpect/的提示,它适用于我通过添加```child.expect(pexpect.EOF)在发送密码后``` – 2016-09-22 13:07:40

阅读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()  

注:所有的代码这里是未经检验的,而你的脚本挂,因为删除产卵对象将挂起,直到t时的假设下写他的命令将终止。

其实,我尝试了很多这些替代方法,但都没有成功。

  • 调用close()或终止()挂起(包括真假作为参数)
  • 调用wait或读取(-1)或预期(pexpect.EOF)挂
  • 调用产卵再次不关心先前的产卵命令挂起

我做了一些测试与其他命令(如'ftp',他们工作正如我所料,例如,如果你调用.expect('东西')) ,并且在EOF之前找不到东西,它们不会永远等待,它们会抛出异常,所以我认为这与ssh-copy-id有关命令具体。

我认为问题在于,SSH试图打开PTY,并且出于安全原因,它不能在PTY以外的任何地方使用 。这不能很好地工作 与pexpect。

我还有一个SSH客户端:

http://www.digmia.com/index.php?option=com_content&view=article&id=54:Digmia%20Enterprise%20SSH&Itemid=56

它是开源的,你可以使用它。你试图做的是 是更多的命令,但你根本不需要期待。

  1. 首先相应安装到手动,然后做这样的事情:

  2. 运行dssh剂,添加你需要这样的密码:

    dssh-add -l < passwordfile 
    
    • ,或者它是一个安全的机器,即没有其他人可以在那里登录, 这是非常重要的,否则这将是一个巨大的安全性h OLE:

      echo "name-of-server;22;root;password;" | dssh-add -l 
      
    • password文件将是这样的:

      name-of-server;22;root;password; 
      
  3. 而且这样做(与文件的实际内容替换CONTENTS OF ...):

    dssh [email protected] -- echo "CONTENTS OF ~/.ssh/identity.pub" > .ssh/authorized_keys \; chmod og-w .ssh .ssh/authorized_keys 
    
    • 您可以(可选)做

      dssh-add -f passwords 
      

    (请确保没有其他人在做这一切的东西,否则你会 有竞争状态)。

同时,Pexpect的或许应该dssh本身的工作(所以你不需要 使用dssh代理)。但是使用dssh-agent更简单,更安全。

DSSH安装手册包含在tarball中。

我不知道这样做的任何简单的方法,OpenSSH的SSH-copy-id命令是 有关,其中的密码来自非常挑剔......

幸运与否,但OpenSSH客户端似乎是非常挑剔的密码和他们来自哪里。

您可以尝试使用Paramiko Python SSH2库。这里有一个简单的example how to use it with password authentication,然后发出一些shell命令(echo "..." >> $HOME/.ssh/authorized_keys是最简单的)在远程主机上添加你的公钥。