使用Python和subprocess.call执行脚本时出错,而在Bash中正常工作
这是我第一次在这里寻求一点帮助,因为我更习惯在ServerFault上发问。
我正在用Python写一些脚本,感觉这个语言真不错,但我遇到了一个小问题,让我的脚本无法正常工作。
这里是我遇到问题的代码行:
subprocess.call('xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd',shell=True)
我也试过用os.popen来做,所有的变量都设置得很正确。
当我在普通的Linux命令行中执行这个命令时,一切都运行得很好,但当我用Python脚本执行时,却出现了一些奇怪的错误。我甚至把subprocess.call()换成了print函数,以确保我得到的输出和命令的输出完全一致。
我查看了我命令行的环境变量,但它们基本上是一样的……我会把我遇到的错误贴出来,但我不确定这是否和我的问题有关。
在/usr/share/perl5/Config/IniFiles.pm的614行,替换时使用了未初始化的值$lines[0]。在/usr/share/perl5/Config/IniFiles.pm的628行,模式匹配时使用了未初始化的值$_。
我不是Python专家,所以我可能遗漏了一些东西。
提前谢谢你的帮助,
Antoine
编辑
根据miax的建议,我停止使用shell=True。然后我查看了Python的文档,关于subprocess,并使用了以下代码:
cmd = 'xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd'
args = shlex.split(cmd)
subprocess.call(args)
可惜,这并没有改变什么……
编辑2
我按照miax给的建议进行了修改,但仍然遇到上面的错误……这是我使用的代码。
cmd = ['xen-create-image', '--hostname', nom, '--memory', memory, '--partitions=/root/scripts/part.tmp', '--ip', ip, '--netmask', netmask, '--gateway', gateway, '--passwd']
subprocess.call(cmd)
这真的很奇怪……同样的命令在普通命令行中运行得很好……
4 个回答
在你提到的Edit2示例中,出现了问题,你以为你给了xen-create-image
以下选项:
--hostname
--memory
--partitions=...
- 等等
... 但实际上你指定的是以下选项:
--hostname
空格- 空格
--memory
空格 - 空格
--partitions=...
- 等等
你有这一行:
cmd = ['xen-create-image', '--hostname ', nom, ' --memory ', memory, ' --partitions=/root/scripts/part.tmp', ' --ip ', ip, ' --netmask ', netmask, ' --gateway ', gateway, ' --passwd']
但是你需要去掉多余的空格:
cmd = ['xen-create-image', '--hostname', nom, '--memory', memory, '--partitions=/root/scripts/part.tmp', '--ip', ip, '--netmask', netmask, '--gateway', gateway, '--passwd']
在大多数情况下,你不应该使用带有 shell=True
的子进程。最好是把命令的参数以列表的形式传递给它。这样做有几个好处:
- 更安全:想象一下,如果用户传入了
foo; rm -rf /; echo
这样的值,那就很危险了。 - 更可靠:假设某个字符串里包含了
$
符号,shell 会把它当成环境变量来处理,结果可能会出乎意料。
虽然我不知道你的代码和 xen-create-image
是什么,但我猜这可能是你遇到问题的原因。
另外,确保检查一下命令的退出代码是否为零,如果不是,要采取相应的措施。(如果你确定它总是会是零,可以使用 check_call
,如果不是零就会抛出错误;这样一来,如果出现问题,你至少会知道会有什么样的反应。)
这个 xen-create-image
脚本开头有没有加上哈希bang?也就是说,第一行是不是像这样:
#!/bin/sh
这点你可以先检查一下。还有,你可以试着用下面的方式来调用你的命令:
cmd = ['/bin/sh', '-c', 'xen-create-image --hostname %s --memory %s --partitions=/root/scripts/part.tmp --ip %s --netmask %s --gateway %s --passwd' % (nom, memory, ip, netmask, gateway)]
subprocess.call(cmd, shell=False)
你可能想打印一下 cmd
,这样可以确认你要运行的命令是正确的(也就是检查一下替换的内容)。