为什么在 shell 脚本中使用 sleep 命令时,它是一个独立的进程,而其他命令似乎不是?

为什么在 shell 脚本中使用 sleep 命令时,它是一个独立的进程,而其他命令似乎不是?

我正在我的 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.sh31110,当我执行命令时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

这里有两个方面需要考虑:

  1. echo并且pwd确实不能显示为独立进程,因为它们是bashshell 的内置命令(请参阅例如的输出type echo- 但请注意,它们可以很好地实现为外部可执行文件,并且什么是或不是作为内置或外部程序实现的,在不同的 shell 中有所不同)。
  2. df另一方面,由 shell 启动的命令调用外部可执行文件(例如)独立的进程,但它们通常完成得如此之快,以至于您将很难用 , “捕捉”它们ps(即它们在ps启动时已经完成,因此不会出现在输出中)。

答案2

sleep是一个外部进程,因为 Bash 默认不提供它的内置版本。这并不难做到,因为程序几乎只运行一个系统调用,但实现之间存在差异,有些不限于整数值,有些需要像m分钟等说明符。

df并且ps通常也是外部进程。df可能运行得太快,你无法捕捉到它(在我的系统上,显示需要 0.003 秒才能运行它),但几乎必然time df的输出也包含进程本身,你可以使用例如查看。pspsps -ef |grep ps

另一方面,echopwd内置于 Bash 中,您可以通过运行 例如 来得知type echo。应该说echo is a shell builtin。两者都不是必须的,并且它们通常也可用/bin/echo/bin/pwd或者/usr/bin/如果您的系统有单独的/binand /usr/bin)。pwd可以是外部的,因为当前工作目录继承给子进程。另一方面,cd 不能,因为对工作目录的更改不会影响父进程。

sleep您还可以有一个在内部实现、df、等的psshell 。cp例如,Busybox 包含所有这些的实现。然而,我的系统上的进程仍然派生另一个进程来运行sleep(但似乎没有这样做df)。

答案3

简短的回答:因为这就是系统的设计方式。很久以前设计 Unix 的人们必须做出决定,哪些命令将是内部命令(由 shell 本身识别和执行),哪些命令将是外部命令(通过单独的二进制文件/进程运行)。

某些命令,如cdpwdset显然必须是内部命令,因为它们引用 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在此会话中尚未使用,因此该命令仅显示它的路径。

相关内容