Linux中如何讓進程到後臺運行?Linux裏面程序一直運行不被中斷

本文主要來自https://fukun.org/archives/06281192.html 和 http://blog.csdn.net/wangjun_1218/article/details/6835800

外加一點自己的實踐。


原文如下:

https://fukun.org/archives/06281192.html

在Linux中,如果要讓進程在後臺運行,一般情況下,我們在命令後面加上&即可,實際上,這樣是將命令放入到一個作業隊列中了:

Example
1
2
3
4
5
$ ./test.sh &
[1] 17208
 
$ jobs -l
[1]+ 17208 Running                 ./test.sh &

對於已經在前臺執行的命令,也可以重新放到後臺執行,首先按ctrl+z暫停已經運行的進程,然後使用bg命令將停止的作業放到後臺運行:

Example
1
2
3
4
5
6
7
8
$ ./test.sh
[1]+  Stopped                 ./test.sh
 
$ bg %1
[1]+ ./test.sh &
 
$ jobs -l
[1]+ 22794 Running                 ./test.sh &

但是如上方到後臺執行的進程,其父進程還是當前終端shell的進程,而一旦父進程退出,則會發送hangup信號給所有子進程,子進程收到hangup以後也會退出。如果我們要在退出shell的時候繼續運行進程,則需要使用nohup忽略hangup信號,或者setsid將將父進程設爲init進程(進程號爲1)

Example
1
2
3
4
5
6
7
8
9
$ echo $$
21734
 
$ nohup ./test.sh &
[1] 29016
 
$ ps -ef | grep test
515      29710 21734  0 11:47 pts/12   00:00:00 /bin/sh ./test.sh
515      29713 21734  0 11:47 pts/12   00:00:00 grep test
Example
1
2
3
4
5
6
$ setsid ./test.sh &
[1] 409
 
$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515        413 21734  0 11:49 pts/12   00:00:00 grep test

上面的試驗演示了使用nohup/setsid加上&使進程在後臺運行,同時不受當前shell退出的影響。那麼對於已經在後臺運行的進程,該怎麼辦呢?可以使用disown命令:

Example
1
2
3
4
5
6
7
8
9
10
11
$ ./test.sh &
[1] 2539
 
$ jobs -l
[1]+  2539 Running                 ./test.sh &
 
$ disown -h %1
 
$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515       2542 21734  0 11:52 pts/12   00:00:00 grep test

另外還有一種方法,即使將進程在一個subshell中執行,其實這和setsid異曲同工。方法很簡單,將命令用括號() 括起來即可:

Example
1
2
3
4
5
$ (./test.sh &)
 
$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515      12483 21734  0 11:59 pts/12   00:00:00 grep test

注:本文試驗環境爲Red Hat Enterprise Linux AS release 4 (Nahant Update 5),shell爲/bin/bash,不同的OS和shell可能命令有些不一樣。例如AIX的ksh,沒有disown,但是可以使用nohup -p PID來獲得disown同樣的效果。

還有一種更加強大的方式是使用screen,首先創建一個斷開模式的虛擬終端,然後用-r選項重新連接這個虛擬終端,在其中執行的任何命令,都能達到nohup的效果,這在有多個命令需要在後臺連續執行的時候比較方便:

Example
1
2
3
4
5
6
7
8
$ screen -dmS screen_test
 
$ screen -list
There is a screen on:
        27963.screen_test       (Detached)
1 Socket in /tmp/uscreens/S-jiangfeng.
 
$ screen -r screen_test
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
現在說說我的問題和解決方法:
我想在Ubuntu服務器上掛載一個socket通信的小程序,是一個server,我想讓這個程序一直運行着。可是我發現一旦沒有客戶端來連接它,沒幾分鐘,改程序自動關閉。這是個令人頭疼的問題。
根據上面指導,解決方法如下:
輸入指令:

echo $$

nohup ./tcp_demo &

ps -ef |grep tcp_demo

說明:tcp_demo是要運行的程序名稱
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

原文如下:
http://blog.csdn.net/wangjun_1218/article/details/6835800
PS: 其實這並不是原文地址,這個地址的文章也是轉載的,不過我發現他附的原文地址不可訪問了,所以姑且把這個當做是原文吧

nohup、setsid、&和disown
2010-04-02 15:16
在執行命令時,偶爾會碰到需要讓對應進程無間斷執行的情況。前段時間看到IBM官網的一篇文章,由於不讓轉載(原文位置:IBM),遂簡單記錄如下:

我們知道,當用戶註銷(logout)或者網絡斷開時,終端會收到 HUP(hangup)信號從而關閉其所有子進程。因此,我們的解決辦法就有兩種途徑:要麼讓進程忽略 HUP 信號,要麼讓進程運行在新的會話裏從而成爲不屬於此終端的子進程。

1. nohup
顯而易見,nohup命令的功能是使進程忽略hangup信號,從而持續執行。nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標準輸出和標準錯誤缺省會被重定向到 nohup.out 文件中。一般我們可在結尾加上"&"來將命令同時放入後臺運行,也可用">filename 2>&1"來更改缺省的重定向文件名。
如:nohup myUbuntuSourceSyncCmd.pl >./sources/ubuntu/sync.log 2>&1 &
這樣起到了三個效果:進程後臺執行;忽略hangup信號;輸出重定向。

2. setsid
setsid中的sid指的是session id,意指以該命令運行的進程是一個新的session,因此其父進程id不屬於當前終端。實際上,setsid運行的進程,其父進程id(PPID)爲1(init 進程的 PID)。因此,setsid解決問題用的是第二種途徑。
如:setsid myUbuntuSourceSyncCmd.pl >./sources/ubuntu/sync.log 2>&1 &
格式與nohup相仿,後臺運行也需加上&,但輸出重定向必須手動設置。

3. 括號()與&
&代表後臺運行(注意輸出並沒有被重定向);此外,我們知道,將一個或多個命名包含在“()”中就能讓這些命令在子 shell 中運行中,從而擴展出很多有趣的功能,我們現在要討論的就是其中之一。
當我們將"&"也放入“()”內之後,我們就會發現所提交的作業並不在作業列表中,也就是說,是無法通過jobs來查看的。
如:(myUbuntuSourceSyncCmd.pl >./sources/ubuntu/sync.log 2>&1 &)
以這種方式運行程序,新提交的進程的父 ID爲1,並不是當前終端的進程 ID。因此並不屬於當前終端的子進程,從而也就不會受到當前終端的 HUP 信號的影響了。

4. disown
如果我們未加任何處理就已經提交了命令,這時想加 nohup 或者 setsid 已經爲時已晚,只能通過作業調度和 disown 來解決這個問題了。讓我們來看一下 disown 的幫助信息:
disown [-ar] [-h] [jobspec ...]
Without options, each jobspec is  removed  from  the  table  of
active  jobs.   If  the -h option is given, each jobspec is not
removed from the table, but is marked so  that  SIGHUP  is  not
sent  to the job if the shell receives a SIGHUP.  If no jobspec
is present, and neither the -a nor the -r option  is  supplied,
the  current  job  is  used.  If no jobspec is supplied, the -a
option means to remove or mark all jobs; the -r option  without
a  jobspec  argument  restricts operation to running jobs.  The
return value is 0 unless a jobspec does  not  specify  a  valid
job.
可以看出,我們可以用如下方式來達成我們的目的。
a. 用disown -h jobspec 來使某個作業忽略HUP信號。
b. 用disown -ah 來使所有的作業都忽略HUP信號。
c. 用disown -rh 來使正在運行的作業忽略HUP信號。
需要注意的是,當使用過 disown 之後,會將把目標作業從作業列表中移除,我們將不能再使用jobs來查看它,但是依然能夠用ps -ef查找到它。
但是還有一個問題,這種方法的操作對象是作業,如果我們在運行命令時在結尾加了"&"來使它成爲一個作業並在後臺運行,那麼就萬事大吉了,我們可以通過jobs命令來得到所有作業的列表。但是如果並沒有把當前命令作爲作業來運行,如何才能得到它的作業號呢?答案就是用 CTRL-z(按住Ctrl鍵的同時按住z鍵)了!
CTRL-z 的用途就是將當前進程掛起(Suspend),然後我們就可以用jobs命令來查詢它的作業號,再用bg jobspec 來將它放入後臺並繼續運行。需要注意的是,如果掛起會影響當前進程的運行結果,慎用此方法。
示例:
root@ubuntu-server:/mnt/ftp# jobs
[1]+  Running                 ./sync_mirror.sh &
root@ubuntu-server:/mnt/ftp# disown -h %1
root@ubuntu-server:/mnt/ftp# ps -ef|grep sync_mirror.sh 
root      8650 22271  0 15:08 pts/0    00:00:00 grep sync_mirror.sh
root     16748 22271  0 Mar31 pts/0    00:00:00 /bin/sh -e ./sync_mirror.sh

另外還有一個命令screen。screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個真實終端下運行多個全屏的僞終端。screen 的參數很多,具有很強大的功能。本篇不做介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章