使用Twisted在远程系统上运行命令

时间:2011-08-06 00:24:27

标签: python twisted

我正在尝试使用Twisted编写客户端/服务器,这将允许客户端在服务器上发出远程命令并实时接收响应数据。即如果我运行$> ssh server someProg.sh,我将在“实时”中看到结果,而不是在流程结束时立即查看结果。 Twisted中有可能出现这种情况吗?感谢。

2 个答案:

答案 0 :(得分:4)

绝对。正如评论中已经提到的,您可以通过connecting to the SSH server directly with Twisted's "conch" library执行此操作。这是更具可扩展性(您可以在没有任何额外进程的情况下打开大量连接)并且更具可移植性(它可以在Windows上运行)但它不会考虑您的OpenSSH配置,并且您必须编写一堆额外的代码来处理用主机密钥验证之类的东西。另一个问题并没有直接解决你的主要问题,也就是输出到达时的处理。

简单的回答是“是”,但是这是一个演示程序,它产生几个子进程并显示它们的输出。您可以将sys.executable替换为另一个要生成的程序(例如ssh),它的工作方式完全相同。

import os, sys

from twisted.internet.protocol import ProcessProtocol
from twisted.internet import reactor
from twisted.internet.defer import Deferred, gatherResults

script = """
import time
for x in range(3):
    time.sleep(1)
    print(x)
"""

class SimpleProcess(ProcessProtocol):
    def __init__(self, id, d):
        self.id = id
        self.d = d
    def outReceived(self, out):
        print('Received output: {out} from: {proc}'
              .format(out=repr(out), proc=self.id))
    def processEnded(self, reason):
        self.d.callback(None)

ds = []
for x in range(3):
    d = Deferred()
    reactor.callLater(
        x * 0.5, reactor.spawnProcess, SimpleProcess(x, d),
        sys.executable, [sys.executable, '-u', '-c', script],
        os.environ)
    ds.append(d)

gatherResults(ds).addBoth(lambda ignored: reactor.stop())

reactor.run()

答案 1 :(得分:-1)

您可以使用paramiko lib http://www.lag.net/paramiko/

import paramiko

class XXX():

def ssh_processing(self, params):

        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy() )

        ssh_connection = ssh.connect(ip, username=params['username'] , password=params['password'])

        result = self.exec_ssh(ssh, cmd)

def exec_ssh(self, ssh, cmd):
    self._log('Exec [%s]' % cmd)
    ( stdin, stdout, stderr ) = ssh.exec_command(cmd)
    data = {
            'stdin'  : '', #self._read_all(stdin),
            'stdout' : self._read_all(stdout), 
            'stderr' : self._read_all(stderr)
        }
    if len(data['stderr']):
        msg = 'SSH Error: [%s]' % data['stderr']
        self._error(msg)

    if 'command not found' in data['stderr']:
        raise Exception(msg)

    return data