我正在我的 Ubuntu 上编写一个名为如下的bash
脚本:test.sh
#!/bin/bash
while true; do
echo 'abc' # pwd, df...
sleep 1
done
当我在一个终端执行时./test.sh
,我打开另一个终端来执行以下命令:
$ pgrep test
31110
$ ps -ef | grep sleep
me 31140 31110 0 20:58 pts/1 00:00:00 sleep 1
me 31142 16389 0 20:58 pts/0 00:00:00 grep --color=auto sleep
$ ps -ef | grep sleep
me 31146 31110 0 20:58 pts/1 00:00:00 sleep 1
me 31148 16389 0 20:58 pts/0 00:00:00 grep --color=auto sleep
$ ps -ef | grep sleep
me 31150 31110 0 20:58 pts/1 00:00:00 sleep 1
me 31152 16389 0 20:58 pts/0 00:00:00 grep --color=auto sleep
所以,进程的PID./test.sh
是31110
,当我执行命令时ps -ef | grep sleep
,我得到许多进程sleep 1
(PID是31140
,,31146
... 31150
),它们都是该进程的子进程./test.sh
。
好吧,现在看来我可以理解一切, 的子进程来自 的sleep 1
循环while true
。
然而,当我尝试时ps -ef | grep echo
,我什么也没得到。我还尝试执行其他命令,例如pwd
, df
,但它们也无法grep
编辑。
所以我的问题是为什么该命令sleep
是一个独立的进程而其他命令不是。
答案1
这里有两个方面需要考虑:
echo
并且pwd
确实不能显示为独立进程,因为它们是bash
shell 的内置命令(请参阅例如的输出type echo
- 但请注意,它们可以很好地实现为外部可执行文件,并且什么是或不是作为内置或外部程序实现的,在不同的 shell 中有所不同)。df
另一方面,由 shell 启动的命令调用外部可执行文件(例如)是独立的进程,但它们通常完成得如此之快,以至于您将很难用 , “捕捉”它们ps
(即它们在ps
启动时已经完成,因此不会出现在输出中)。
答案2
sleep
是一个外部进程,因为 Bash 默认不提供它的内置版本。这并不难做到,因为程序几乎只运行一个系统调用,但实现之间存在差异,有些不限于整数值,有些需要像m
分钟等说明符。
df
并且ps
通常也是外部进程。df
可能运行得太快,你无法捕捉到它(在我的系统上,显示需要 0.003 秒才能运行它),但几乎必然time df
的输出也包含进程本身,你可以使用例如查看。ps
ps
ps -ef |grep ps
另一方面,echo
和pwd
内置于 Bash 中,您可以通过运行 例如 来得知type echo
。应该说echo is a shell builtin
。两者都不是必须的,并且它们通常也可用/bin/echo
(/bin/pwd
或者/usr/bin/
如果您的系统有单独的/bin
and /usr/bin
)。pwd
可以是外部的,因为当前工作目录继承给子进程。另一方面,cd
不能,因为对工作目录的更改不会影响父进程。
sleep
您还可以有一个在内部实现、df
、等的ps
shell 。cp
例如,Busybox 包含所有这些的实现。然而,我的系统上的进程仍然派生另一个进程来运行sleep
(但似乎没有这样做df
)。
答案3
简短的回答:因为这就是系统的设计方式。很久以前设计 Unix 的人们必须做出决定,哪些命令将是内部命令(由 shell 本身识别和执行),哪些命令将是外部命令(通过单独的二进制文件/进程运行)。
某些命令,如cd
、pwd
或set
显然必须是内部命令,因为它们引用 shell 的内部状态,因此它们不能由外部进程执行。对于大多数其他命令,设计者可以选择该命令是内部命令还是外部命令 - 事实上,不同 shell 之间在这方面存在差异。
例如,有一些旧的系统/shellecho
是外部命令。如今,echo
几乎所有 shell 中都有一个内部命令,但是传统的/bin/echo
外部命令仍然存在(至少在 Linux 中),可能是出于兼容性原因。
正如另一个答案中所述,使用命令type
(显然必须是内部命令,例如cd
),您可以检查哪些命令是内部命令,哪些命令是外部命令:
raj@rafa:~$ type echo
echo is a shell builtin
raj@rafa:~$ type df
df is hashed (/bin/df)
raj@rafa:~$ type ps
ps is /bin/ps
raj@rafa:~$
请注意“df is hashed”消息 - 这意味着该df
命令已在此 shell 会话中使用,因此 shell 会记住它的位置,并且当我想运行它时不必再次在磁盘上搜索它。另一方面,ps
在此会话中尚未使用,因此该命令仅显示它的路径。