Bash shell进程问题浅析(续)

上文,再来看一下exec这个bash shell内置命令:

exec [-cl] [-a name] [command [arguments]]
              If command is specified, it replaces the shell.  No new process is created.  The arguments become the arguments to command.  If the -l option is supplied, the shell places a dash at the beginning of the zeroth argument passed to command.  This is what login(1) does.  The -c option causes command  to  be executed with an empty environment.  If -a is supplied, the shell passes name as the zeroth argument to the executed command.  If command cannot be executed for some reason,  a  non-interactive  shell  exits,  unless the shell option execfail is enabled, in which case it returns failure.  An interactive shell returns failure if the file cannot be executed.  If command is not specified,  any  redirections  take  effect in the current shell, and the return status is 0.  If there is a redirection error, the return status is 1.  

可以看到,当用exec执行一个命令时,不会产生新的进程,并且这个命令会替换掉当前的bash shell进程。让我们看个例子。在一个终端执行下列命令:

[root@localhost ~]# echo $$
[root@localhost ~]# exec sleep 60


[root@localhost ~]# ps -ef | grep 22330
root     22330 22329  0 05:50 pts/0    00:00:00 sleep 60
root     22361 22345  0 05:52 pts/1    00:00:00 grep --color=auto 22330

可以看到22330号进程变成了sleep 60,而不是bash shell进程了。60秒后,sleep 60进程结束了,终端也退出了:

[root@localhost ~]# ps -ef | grep 22330
root     22363 22345  0 05:56 pts/1    00:00:00 grep --color=auto 22330

最后,通过演示经典的《Shell十三问》《exec跟source差在哪?》一章结尾的例子,再好好理解一下bash shell进程的相关问题:

echo "PID for before exec/source/fork:$$"
export A
echo " \$A is $A"
case $1 in
        echo "using exec..."
        exec ./ ;;
        echo "using source..."
        . ./ ;;
        echo "using fork by default..."
        ./ ;;
echo "PID for after exec/source/fork:$$"
echo " \$A is $A"

echo "PID for $$"
echo " get \$A=$A from"
export A
echo " \$A is $A"

(1)执行“./ fork”:

[root@localhost ~]# ./ fork
PID for before exec/source/fork:22390 $A is B
using fork by default...
PID for 22391 get $A=B from $A is C
PID for after exec/source/fork:22390 $A is B


(2)执行“./ source”:

[root@localhost ~]# ./ source  
PID for before exec/source/fork:22393 $A is B
using source...
PID for 22393 get $A=B from $A is C
PID for after exec/source/fork:22393 $A is C


(3)执行“./ exec”:

[root@localhost ~]# ./ exec
PID for before exec/source/fork:22396 $A is B
using exec...
PID for 22396 get $A=B from $A is C