当这些参数包含变量的组合字符串时,我对subprocess.call命令参数的语法有点不稳定
我有4个变量用于使用os.system成功运行的单个完整命令字符串:
路径
os.system(“sshpass -p%s scp%s @%s:/var/tmp/*Metrics.csv%s”%(userPWD,userName,hostName,path))
现在将它转换为subprocess.call,它将为我提供所需的输出状态,这个命令字符串的某些方面的格式让我失望,因为subprocess.call文档通常只显示非常简单的命令,如下所示:
subprocess.call(['ls', '-l'])
我转换它的第一个努力看起来像这样:
subprocess.call(["sshpass", "-p", userPWD, "scp", "userName@hostName:/var/tmp/*Metrics.csv", path"])
但是这会在Python 2.7.3中产生以下错误消息:
Traceback (most recent call last):
File "pyprobeConnect.py", line 73, in <module>
get_csvPassFail = subprocess.Popen("sshpass -p %s scp %s@%s:/var/tmp/*Metrics.csv %s" % (userPWD, userName, hostName, path)).read()
File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
答案 0 :(得分:0)
当您包含*
时,您需要传递shell=True
,如果您传递shell=True
,则需要将第一个参数指定为字符串而不是列表。
subprocess.call("sshpass -p %s scp %s@%s:/var/tmp/*Metrics.csv %s" % (userPWD, userName, hostName, path),shell=True)
答案 1 :(得分:0)
一般情况下,我不认为在shell=True
家庭使用subprocess
是一个好主意。这是一个非常着名的攻击传播(或不便)。恶意(或无能)用户可能注入任意shell命令。在您的情况下,密码字段似乎在用户的控制之下,因此可能存在风险。一个人不使用os.system
的原因是为了防止出现这种错误。
在此,我假设您正在使用scp
将文件从远程数据库提取到本地主机。在这种情况下,shell *
globbing并不重要,因为它是由远程shell扩展的。
您的堆栈跟踪说明问题在于无法找到您的案例sshpass
中的可执行文件。这可能是因为包含可执行文件的目录不在您的PATH
环境变量中。
要解决此问题,您可以在调用命令时暂时修改PATH
,在以下假Python中(您需要填写自己的详细信息):
import os
cur_path = os.environ["PATH"]
if dir_of_your_executable not in cur_path:
cmd_path = "%s:%s" % (dir_of_your_executable, cur_path)
else:
cmd_path = cur_path
cmd_env = os.environ.copy().update(PATH=cmd_path)
subprocess.call(["sshpass", "rest", "of", "your", "command"], env=cmd_env)
代码首先会检查sshpass
的目录是否在PATH
中。如果没有,则它以PATH
为前缀,用于执行命令。
或者,只需使用绝对路径:
subprocess.call(["/path/to/sshpass", "rest", "of", "your", "command"])
最后,请注意:只对sshpass
说不。它不安全,因此是邪恶的。在执行自动命令之前,通过启动ssh-agent
来使用基于公钥的SSH身份验证。使用密码进行分配,尤其是sshpass -p
传递的密码。他们是邪恶的。只是说不。