如果我从/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
确实可以按预期工作(CompletedProcess
的returncode
为0
,或者subprocess.CalledProcessError
(。我试过printf
、echo
、ls
、cat
、which
。。。
那么,command
有什么特别之处呢?
command
是bash
和其他shell的内置关键字。很可能,您的系统在其搜索PATH
中没有实际的/usr/bin/command
可执行文件。
subprocess.run('command -v lualatex', shell=True)
大致相当于默认使用bash
shell的系统上的subprocess.run(['bash', '-c', 'command -v lualatex'])
。然后bash
将command
解释为其内置版本,而不是系统可执行版本。
另一方面,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)