【问题标题】:Python subprocess.check_output() seems to ignore argumentsPython subprocess.check_output() 似乎忽略了参数
【发布时间】:2015-10-28 20:36:21
【问题描述】:

首先,我尽可能多地阅读了与 subprocess.check_output() 相关的问题,但仍然难以确定问题。

如果我在shell中执行kill -l 1,我会得到1对应的信号名称,即HUP。我的 python 脚本中需要相同的行为,所以我使用:

>>> subprocess.check_output(['kill', '-l', '1'])
b'HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT\nCHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS\n'

子进程似乎忽略了参数列表中的“1”,而是执行kill -l

我尝试了不同的版本,参数为列表或字符串,shell 选项为 True 和 False,但似乎都不起作用。

任何想法可能是什么原因?在 Ubuntu14.04 上使用 python3.4。

谢谢!

【问题讨论】:

  • subprocess.check_output(['kill', '-l', '1']) 在我的控制台上按预期工作.-.

标签: python shell subprocess


【解决方案1】:

可能的原因:你的shell中的kill命令正在执行一个shell内置(大多数shell都有一个,因为当你有失控的fork炸弹等时,你需要能够在没有进程启动的情况下杀死),而check_output(默认不在shell中执行)正在运行PATH中的kill可执行文件(通常是/bin/kill,但并非总是如此,在bash中运行type -P kill会告诉你该可执行文件在哪里是)。

奇怪的是,内置支持您正在寻找的开关,而可执行文件不支持。在bash 中,尝试运行type -P kill,然后显式运行/full/path/to/kill -l 1 以查看kill check_output 是否发现实际上支持该调用。 kill 的不同实现之间通常存在细微差别。

对此的最佳解决方案可能是避免昂贵且毫无意义的subprocess 启动并检查信号的 Python 定义。例如,在 Python 3.5 中,构建从 Python 已知的信号到它们的 Python 名称的映射很简单:

import signal

sigdict = {sig.value: sig.name for sig in signal.Signals}

print(sigdict[1])
CTRL_BREAK_EVENT  # <-- The output on my Windows box. On your machine, it would probably be SIGHUP

在名称不是 enums 的旧 Python 中,您可以使用模块的 dir 使用类似的代码,过滤 __module__signal 且其值为整数的名称以构造映射.

【讨论】:

  • 只是为了加强,在我的 linux mint 上,这正是发生的事情。 /bin/kill -l 1HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS
  • @tdelaney:感谢您的确认。我的旧笔记本电脑刚刚死机,而我正在使用一台没有正常 Linux VM 进行测试的新笔记本电脑,所以我无法确认,但似乎很有可能。 kill 在 shell 内置程序和可执行程序之间存在一些最大的差异(我总是被可执行程序支持进程组通过传递 -pid 杀死,而内置程序根本不支持,这就是为什么我怀疑这是原因)。
  • 谢谢,这似乎是问题所在。 /bin/kill -l 1 忽略 1 标志,而“内置” kill 提供所需的输出。有什么建议可以解决python问题吗? type -P kill 指向/bin/kill,内置kill 是不是我在某处能找到的常规程序?
  • @balint:我添加了一个替代方案,可以避免启动昂贵且无意义的子进程。如果你真的想使用内置的,你可以使用subprocess.check_output('kill -l 1', shell=True)subprocess.check_output(['bash', '-c', 'kill -l 1']) 来显式调用一个shell,然后它会为你运行kill。如果要传递的参数来自用户(漏洞来源),这不是一个好主意,尽管在 Python 3.3+ 上可以通过在用户提供的值上使用 shlex.quote 来缓解这种情况。
猜你喜欢
  • 1970-01-01
  • 2015-06-21
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
  • 2021-10-28
  • 2016-09-30
  • 2016-03-16
相关资源
最近更新 更多