問題引出:這幾天遇到一個問題,調用別人寫的nginx啊、logstash啊等等一些啓動腳本(如:nginx_start.sh)的時候,ps查看了一下進程,發現應用起來後,啓動腳本的進竟然也還在,看了一下腳本,裏面用nohup方法,理論上進程起來後,啓動腳本的進程不應該還在纔對,針對這個現象,自己做了一些測試。
一、模仿寫了一個nginx“啓動”腳本,如下:
#!/bin/bash
## 狀態信息
nginx_status()
{
# 查看狀態
if [ "x${pid}" != "x" ]; then
echo "nginx (PID:$(echo -n ${pid})) is running..."
else
echo "nginx was stopped"
fi
}
nginx_start()
{
# 判斷是否已啓動
[ "x${pid}" = "x" ] && nohup sleep 300 &
sleep 1
nginx_status
}
if [ "$USER" = "root" ]; then
case $1 in
start)
nginx_start
;;
status)
nginx_status
;;
*)
echo "nothing"
esac
else
echo "User is $USER. You must be apps to run this script!"
fi
2、執行這個進程,出現如下的結果:啓動進程盡然還在。
pstree查看一下:
3、多次測試,排除了啓動腳本中sleep 1、後面調用nginx_status和最後的case的可能性。(這裏測試過程比較簡單,略)
4、多次測試,排除一些可能性後,再研究啓動腳本的寫法,
理論上來說,使用nohup &會進入後臺執行,並不會影響父進程的正常退出,爲了驗證這個,做了如下嘗試:
執行後發現:並不會出現啓動腳本的進程。
5、這樣,就把問題集中到了nohup &前面的語句了,仔細的想了一下,[ "x${pid}" = "x" ] && nohup sleep 300 & 這條語句,會不會是最後的&將命令放入後臺執行的時候失敗了,也就是會所這條語句並沒有像預想中的那樣進入後臺執行,即進入後臺“失敗”,沒有真正意義上的進入後臺,從而影響了父進程的正常退出,這裏只需要把sleep 300放入後臺進行就可以了,爲了排除前面可能帶來的干擾,做了如下測試:
結果發現:啓動腳本的進程沒有了,也就是說sleep 300放入後臺執行並沒有影響父進程的退出。
6、上面的測試中,進入後臺運行的程序都是需要執行一定時間或者是一直在執行的(引出這些測試的例子就是這種類型),那麼如果是進入後臺執行的程序很快就能執行完,結果會怎樣?
運行結果:並沒有發現啓動腳本的進程
二、總結:
個人總結:查看一下資料後,個人覺得原因可能如下:nohup &的執行依賴於前面[ "x${pid}" = "x" ] 的執行結果爲真,即進入後臺的程序依賴了父進程的一些資源,例如文件資源等,所以在子進程(後臺進程)沒有運行結束之前(文中模仿的就是進入後臺的子進程還在運行中),這些依賴的資源沒有被釋放,導致父進程無法正常退出,一旦子進程執行完後(文中sleep 300後)依賴的父進程的資源釋放後,父進程正常退出。
求其他高見。謝謝