Python执行远程程序

4

我正在使用Python重新编写一个旧的Windows应用程序,并在Linux上运行。最初,新应用程序需要调用旧应用程序,以便我们在仍然使用旧应用程序的客户和使用新应用程序的客户之间具有一致的结果。

所以我有一个Linux盒子,就在一个Windows盒子旁边,我想让Linux盒子上的一个进程执行一个命令,捕获结果(同步)。

我的初始想法是在Windows盒子上编写一个Web服务,但这意味着除了旧应用程序外还要在Windows机器上运行Web服务器。

然后我想,使用Twisted.Conch可能允许我仅通过网络执行命令而不需要运行Web服务器等其他额外开销,但是我假设在Windows机器上运行ssh服务器也会产生开销。

除了Web服务或SSH外,是否还有其他使用Python在不同机器上启动同步进程的替代方法?如果Web服务或SSH是最佳选择,那么我是否应该考虑使用Twisted?


2
同步 - 意味着“实时”,我希望在Linux上执行时暂停并等待Windows的响应。与异步相反,我会将某个工作单元提交给Windows,然后继续在Linux上做其他事情,并在Windows完成时得到通知。 - Matthew J Morrison
5个回答

5

我最终选择了SSH + Twisted。在Windows机器上,我设置了freeSSHd作为Windows服务。在尝试让paramiko工作并遇到大量公钥/私钥问题的挫败后,我决定尝试Twisted,只用了几分钟就搞定了。所以,我根据Twisted文档编写/窃取了这个代码,以实现我在Linux中所需的SSH客户端功能。

from twisted.conch.ssh import transport
from twisted.internet import defer
from twisted.conch.ssh import keys, userauth
from twisted.conch.ssh import connection
from twisted.conch.ssh import channel, common
from twisted.internet import protocol, reactor

class ClientTransport(transport.SSHClientTransport):
    def verifyHostKey(self, pubKey, fingerprint):
        return defer.succeed(1)
    def connectionSecure(self):
        self.requestService(ClientUserAuth('USERHERE', ClientConnection()))

class ClientUserAuth(userauth.SSHUserAuthClient):
    def getPassword(self, prompt=None):
        return 
    def getPublicKey(self):
        return keys.Key.fromString(data=publicKey)
    def getPrivateKey(self):
        return defer.succeed(keys.Key.fromString(data=privateKey))

class ClientConnection(connection.SSHConnection):
    def serviceStarted(self):
        self.openChannel(CatChannel(conn=self))

class CatChannel(channel.SSHChannel):
    name = 'session'
    def channelOpen(self, data):
        data = 'abcdefghijklmnopqrstuvwxyz' * 300
        self.return_data = ''
        self.conn.sendRequest(self, 'exec', common.NS('C:\helloworld %-10000s' % data), wantReply=True)
    def dataReceived(self, data):
        self.return_data += data
    def closed(self):
        print "got %d bytes of data back from Windows" % len(self.return_data)
        print self.return_data
        self.loseConnection()
        reactor.stop()

if __name__ == "__main__":
    factory = protocol.ClientFactory()
    factory.protocol = ClientTransport
    reactor.connectTCP('123.123.123.123', 22, factory)
    reactor.run()

这已经非常好了!


4
另一个选择是paramiko。它是一个实现SSH的Python库。我使用它来远程执行命令并将文件传输到运行SSH服务器的Windows设备。问题在于,由于Windows命令shell的特殊性,它无法正确捕获stdout。您可能会在基于twisted的解决方案中遇到同样的问题。
您想要捕获哪种结果?

在这个阶段,我还不确定结果的样子,但我假设需要从stdout中获取它们。 - Matthew J Morrison
我接受这个答案,不是因为它必然是“正确的”,我认为在这个问题上真的没有对错之分,但我将采用SSH路线并很可能使用Paramiko。 - Matthew J Morrison

1

1
谢谢,我会看一下 - 如果最终我使用这个答案而不是其他提交的答案,我会接受这个答案。 - Matthew J Morrison

1

在我看来,RPC是正确的答案。

我认为:

  • 对于Windows机器,使用SimpleXMLRPCServer
  • 对于Linux机器,使用xmlrpclib

从标准库中选择这些库会给你最大的自由度。你可以根据需要进行实现,而不必担心Windows API、DCOM等过于庞杂的技术。无论在哪台机器上,你都处于Python的领地。

顺便说一下: Twisted当然也是一个很好的选择,所以不用担心;我想苹果的CalDav服务器也是运行在Twisted上的。


0

我经常使用一个名为winexe的小程序,它基于Samba。

这是命令语法的样子,这里有一些安装选项


这有可能有效 - 我对我找到的缺乏文档感到有些不满意。 - Matthew J Morrison
可以理解。安装中似乎没有包含man手册,但至少winexe --help提供了所有命令选项的完整列表。 - ewall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接