使用Python和subprocess.call执行脚本时出错,而在Bash中正常工作

4 投票
4 回答
763 浏览
提问于 2025-04-15 23:10

这是我第一次在这里寻求一点帮助,因为我更习惯在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 个回答

0

在你提到的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']
2

在大多数情况下,你不应该使用带有 shell=True 的子进程。最好是把命令的参数以列表的形式传递给它。这样做有几个好处:

  • 更安全:想象一下,如果用户传入了 foo; rm -rf /; echo 这样的值,那就很危险了。
  • 更可靠:假设某个字符串里包含了 $ 符号,shell 会把它当成环境变量来处理,结果可能会出乎意料。

虽然我不知道你的代码和 xen-create-image 是什么,但我猜这可能是你遇到问题的原因。

另外,确保检查一下命令的退出代码是否为零,如果不是,要采取相应的措施。(如果你确定它总是会是零,可以使用 check_call,如果不是零就会抛出错误;这样一来,如果出现问题,你至少会知道会有什么样的反应。)

0

这个 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,这样可以确认你要运行的命令是正确的(也就是检查一下替换的内容)。

撰写回答