【问题标题】:Problem executing script using Python and subprocces.call yet works in Bash使用 Python 和 subprocces.call 执行脚本的问题在 Bash 中仍然有效
【发布时间】:2010-05-25 22:16:34
【问题描述】:

我第一次在这里寻求一些帮助,因为我更像是一个 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 shell 中执行有问题的命令时,它工作得非常好,但是当我使用我的 Python 脚本执行它时,我得到了奇怪的错误。我什至用 print 函数替换了 subprocess.call() 以确保我使用的是命令的确切输出。

我查看了我的 shell 的环境变量,但它们几乎相同......我会发布我遇到的错误,但我不确定它是否与我的问题有关。

在 /usr/share/perl5/Config/IniFiles.pm 第 614 行使用未初始化的值 $lines[0] 替换 (s///)。 在 /usr/share/perl5/Config/IniFiles.pm 第 628 行的模式匹配 (m//) 中使用未初始化的值 $_。

我不是 Python 专家,所以我很可能在这里遗漏了一些东西。

提前感谢您的帮助,

安东尼


编辑

按照 miax 的建议,我停止使用 shell=True。相反,我查看了subprocess 的 Python 文档并使用了以下代码:

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)

遗憾的是,它并没有改变任何东西......


EDIT2

我已经使用了miax给出的提示,但仍然出现上述错误...这是我使用的代码。

cmd = ['xen-create-image', '--hostname', nom, '--memory', memory, '--partitions=/root/scripts/part.tmp', '--ip', ip, '--netmask', netmask, '--gateway', gateway, '--passwd']
subprocess.call(cmd)

这真的很奇怪......当我在常规 shell 中运行它时,确切的命令运行良好......

【问题讨论】:

  • 有点奇怪,当你运行 Python 时它会给你 Perl 错误。非常愚蠢的问题:你确定你使用的是 #!/usr/bin/python 而不是 #!/usr/bin/perl 吗?
  • xen-delete-image 是一个 Perl 脚本。我确实在使用 /usr/bin/python。

标签: python subprocess xen bash


【解决方案1】:

您(在大多数情况下)不想将子进程与shell=True 一起使用。 将参数列表传递给命令。那是

  • 更安全:假设用户设法将foo; rm -rf /; echo 作为一些值传递。
  • 更可靠:假设其中一个字符串包含$ 或其他内容 - 它将由 shell 扩展并替换为该环境变量的内容。

在不知道您的代码和xen-create-image 的情况下,我认为这是您的问题的原因。

PS:请务必查看命令的退出代码是否为零,如果不是,请适当处理。 (如果您确定它始终为零,请使用check_call,如果不是,则会引发;这样,如果失败,您至少会有一个定义的行为。)

【讨论】:

  • 好的,那我用什么?因为不提 shell=False 或什么都没有导致错误...
  • 传递一个列表,例如call(['xen-create-image', '--hostname', nom, '--memory', memory, 'and', 'so', 'on'])(它会导致错误,因为它试图运行一个名为whole字符串的命令,当然它不存在)
【解决方案2】:

xen-create-image 脚本是否以 hashbang 开头?也就是说,第一行类似于

#!/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 以验证这是您打算运行的命令(即检查替换)。

【讨论】:

    【解决方案3】:

    在您失败的 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']
    

    【讨论】:

      【解决方案4】:

      你需要print你正在使用的命令:

      cmd = 'xen-create-image --hostname '+nom+' --memory '+memory+' --partitions=/root/scripts/part.tmp --ip '+ip+' --netmask '+netmask+' --gateway '+gateway+' --passwd'
      print "COMMAND:", cmd
      

      然后将命令粘贴到您的 shell 中以确保它完全一样。

      【讨论】:

      • 我会再试一次 :) 感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 2017-03-08
      • 2012-06-24
      • 1970-01-01
      • 2011-07-07
      • 2018-05-04
      • 1970-01-01
      相关资源
      最近更新 更多