我跟着这个question 我在PostgreSQL中有这个功能:
CREATE OR REPLACE FUNCTION a()
RETURNS void AS
$BODY$
import subprocess
cmd1 = "usr/bin/ssh usera@192.168.10.5 time"
out1, err1 = subprocess.Popen(cmd1,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
plpy.notice(out1)
$BODY$
LANGUAGE plpythonu VOLATILE
这应该登录到指定的服务器并显示其time
。
不管我做什么,我总是得到:
错误:OSError:[Errno 2]没有这样的文件或目录
我唯一没有得到错误的是if cmd1 =“usr / bin / ssh” 但它什么也没做。
我怎样才能让它发挥作用?
答案 0 :(得分:1)
您遇到的问题是Popen()
假定命令是命令+参数列表。
在那里,cmd1
看起来应该更像:
cmd1 = ['/usr/bin/ssh', 'usera@192.168.10.5', 'time']
(除非危险地提供shell=True
,否则您可以保持命令字符串不变。)
您也可以使用:
import shlex
cmd1 = shlex.split("/usr/bin/ssh usera@192.168.10.5 time")
这也包含在Popen()的文档中。
最后注意事项:我从未使用plpythonu
或此SQL版本的代码执行,但我认为您需要指定完整路径SSH作为Lix指出,它是/usr/bin/ssh
而不是usr/bin/ssh
。但是你的主要问题是如何将参数传递给Popen()
。
不要忘记允许SSH使用密钥登录,否则命令可能会挂起,要求在后台输入密码。
看到很多人在没有程序员理解原因的情况下运行系统命令时出现问题,请尝试以下修改以在执行命令时获取输出而不是在结束时(.communicate()
将等待EOL,意味着挂起永远,如果过程永不退出):
CREATE OR REPLACE FUNCTION a()
RETURNS void AS
$BODY$
import subprocess
cmd1 = ["usr/bin/ssh", "usera@192.168.10.5", "time"]
process = subprocess.Popen(cmd1,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT).communicate()
while process.poll() is None:
plpy.notice(process.stdout.readline())
$BODY$
LANGUAGE plpythonu VOLATILE
由于我将STDERR和STDOUT融合在一起并使用readline()
代替read()
,因此效率仍然非常低。此处import select
也许有用。
但是这会给你输出" live"从命令而不是最后的bunkered。它还应该打印命令抛出的任何错误(但仍然挂起,因为错误没有正确关闭应用程序)。
这是一个常见的错误,人们需要更多地阅读这些示例/文档。