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信號,這樣就可以讓整個腳本退出了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM