为什么在subprocess.run()中调用"command-v"会引发FileNotFoundE



如果我从/bin/bash/bin/sh运行command,我会得到类似的结果:

nico@xantico:~$ command -v lualatex
/usr/local/texlive/2021/bin/x86_64-linux/lualatex
nico@xantico:~$ sh
$ command -v lualatex
/usr/local/texlive/2021/bin/x86_64-linux/lualatex
$

(每次返回代码为0(。

如果我从python运行它,看起来我需要使用shell=True,尽管我不明白为什么:

nico@xantico:~$ python
Python 3.8.10 (default, Nov 26 2021, 20:14:08) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.run('command -v lualatex', shell=True)
/usr/local/texlive/2021/bin/x86_64-linux/lualatex
CompletedProcess(args='command -v lualatex', returncode=0)
>>> subprocess.run('command -v lualatex'.split())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.8/subprocess.py", line 493, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.8/subprocess.py", line 858, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/usr/lib/python3.8/subprocess.py", line 1704, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'command'

最令人惊讶的是,它提出了一个FileNotFoundError,而不是subprocess.CalledProcessError

添加CCD_ 7和CCD_。

使用其他东西作为command确实可以按预期工作(CompletedProcessreturncode0,或者subprocess.CalledProcessError(。我试过printfecholscatwhich。。。

那么,command有什么特别之处呢?

commandbash和其他shell的内置关键字。很可能,您的系统在其搜索PATH中没有实际的/usr/bin/command可执行文件。

subprocess.run('command -v lualatex', shell=True)大致相当于默认使用bashshell的系统上的subprocess.run(['bash', '-c', 'command -v lualatex'])。然后bashcommand解释为其内置版本,而不是系统可执行版本。

另一方面,subprocess.run(['command', '-v', 'lualatex'])试图直接调用系统的command可执行文件,但该可执行文件不存在,因此FileNotFoundError。在这种情况下,实际的子进程根本没有派生出来,因为没有可执行文件可调用。

从下面的注释中,您可能需要使用shell=True才能在系统中使用command。由于多种原因,这通常被认为是不安全的。但是,您可以通过正确地转义使用shlex.join发送的参数来减轻一些风险(例如,基本注入(。shlex.join函数将参数列表(第一个是命令名(转换为一个字符串,该字符串可以安全地与shell=True一起使用;它确保完成正确的转义和引用:

import subprocess, shlex
subprocess.run(shlex.join(['command', '-v', 'lualatex']), shell=True)

最新更新