Shell中, 退出整个脚本

Posted littlehb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shell中, 退出整个脚本相关的知识,希望对你有一定的参考价值。

常规做法

cat >test.sh<<EOF‘‘
#!/bin/bash

exit_script(){
    exit 1
}

echo "before exit"
exit_script
echo "after exit"
EOF

chmod a+x test.sh
./test.sh
echo $?

# 输出
before exit
1

可以看到直接使用exit可以退出脚本,并且可以将错误码作为参数传递。下面我们将脚本做一点点改动。

存在的问题

cat >test.sh<<EOF‘‘
#!/bin/bash

exit_script(){
    exit 1
}

echo "before exit"
:|exit_script
echo "after exit"
EOF

chmod a+x test.sh
./test.sh
echo $?

# 输出
before exit
after exit
0

管道(|)中执行exit_script函数,不会退出整个脚本!原因在于,exit只能退出它所在的Shell,而放在管道中执行的命令/函数都是在独立的Shell(Sub-Shell)中执行的,所以上面脚本的进程树是这个样子的:

 PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
17510 26959 26959 26959 pts/0    14049 Ss       0   0:00  \_ -bash
26959 13843 13843 26959 pts/0    14049 S        0   0:00  |   \_ /bin/bash ./test.sh
13843 13844 13843 26959 pts/0    14049 S        0   0:00  |   |   \_ :
13843 13845 13843 26959 pts/0    14049 S        0   0:00  |   |   \_ /bin/bash ./test.sh
13845 13846 13843 26959 pts/0    14049 S        0   0:00  |   |       \_ exit 1

自上往下,各个PID的含义如下表:

PID说明
26959 ./test.sh所在的Shell
13843 管道中:新开的Shell
13844 :命令
13845 管道中exit_shell新开的Shell
13846 exit命令

使用trapkill退出整个脚本

cat >test.sh<<EOF‘‘
#!/bin/bash

export TOP_PID=$$
trap exit 1 TERM

exit_script(){
    kill -s TERM $TOP_PID
}

echo "before exit"
:|exit_script
echo "after exit"
EOF

chmod a+x test.sh
./test.sh
echo $?

# 输出
before exit
1

这里首先在脚本的主进程中捕获(trap) TERM信号: 当主进程接收到TERM信号后,会执行exit 1;再在Sub-Shell中向脚本主进程发送TERM信号,这样就可以让整个脚本退出了!

以上是关于Shell中, 退出整个脚本的主要内容,如果未能解决你的问题,请参考以下文章

源 shell 脚本的退出代码

break跳出循环continue结束本次循环exit退出整个脚本

for循环while循环break循环continue结束本次循环exit退出整个脚本

如何在linux中使用shell脚本杀死进程时获取退出代码=0

在 C 程序中获取 shell 脚本的退出代码

如何在 shell 脚本中捕获 Gradle 退出代码?