众所周知,在运行时bash -c "COMMAND"
(至少在 Linux 的常见版本中),当有一个命令不带任何元字符(空格、制表符或换行符除外)时,bash -c
进程不会分叉,而是通过COMMAND
直接使用execve
系统调用执行来替换自身为了优化,所以结果只会是一个过程。
$ pid=$$; bash -c "pstree -p $pid"
bash(5285)───pstree(14314)
如果存在任何元字符(例如重定向)或多个命令(无论如何都需要一个元字符),bash
则会分叉它执行的每个命令。
$ pid=$$; bash -c ":; pstree -p $pid"
bash(5285)───bash(28769)───pstree(28770)
$ pid=$$; bash -c "pstree -p $pid 2>/dev/null"
bash(5285)───bash(14403)───pstree(14404)
这是一个未记录的优化功能(这意味着它不受保证),还是在某处记录并有保证?
注意:我认为并非所有版本的bash
行为都是如此,并且在某些版本上,它只是被视为实现细节而不是保证,但我想知道是否至少有一些bash
版本明确支持这一点并记录条件为了这。例如,如果;
命令后面有一个字符,没有任何第二个命令,bash
仍然execve
不会分叉。
$ pid=$$; bash -c "pstree -p $pid ; "
bash(17516)───pstree(17658)
我的问题的背景
正如我所提到的,这种行为对于有经验的用户来说是众所周知的1 2bash
,而且我已经熟悉它很长时间了。
几天前,我在Interactive bash shell 中遇到了以下评论:通过命令行选项设置工作目录,其中 @dave_thompson_085 写道:
bash
自动执行(即用其替换自身)最后一个(或唯一的)命令-c
。
我回答说,只有当只有一个命令时,这才是正确的。但后来我想知道:是否有某些版本的bash
最后一个命令可能是 exec
ed 而不是 fork,即使它之前有另一个命令?一般来说,这种行为是否有保证?某些版本是否bash
在源代码之外公开(并详细说明)此功能?