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

发布于 2024-11-28 08:12:20 字数 166 浏览 0 评论 0原文

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

I'm trying to write a Client/Server using Twisted that will allow the client to issue remote commands on the server and receive response data in real time. i.e. If I run $> ssh server someProg.sh, I will see the results in 'real time', not all at once when the process finishes. Is this sort of thing possible in Twisted? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪菊怪哟 2024-12-05 08:12:20

绝对地。正如评论中已经指出的,您可以通过 执行此操作使用 Twisted 的“conch”库直接连接到 SSH 服务器。这更具可扩展性(您可以打开大量连接而无需任何额外的进程)并且更可移植(它可以在 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()

Absolutely. As already noted in a comment, you can do this by connecting to the SSH server directly with Twisted's "conch" library. This is more scalable (you can open lots of connections without any extra processes) and more portable (it can work on Windows) but it won't take into account your OpenSSH configuration, and you have to write a bunch of additional code to deal with things like host key verification. The other question doesn't directly address your main question here, either, which is about the output being processed as it arrives.

The simple answer is "yes", but here's a demonstration program that spawns several subprocesses and displays their output as it goes. You can replace the sys.executable with another program to spawn (i.e. ssh) and it'll work exactly the same way.

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()
雨后彩虹 2024-12-05 08:12:20

您可以使用 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 

You could use 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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文