在linux後臺運行腳本命令和程序的方法大全

 需要在linux後臺執行任務的情況還是經常會遇到的,比如一些費時的操作,或者一些需要長時間存在的程序。當然你也可以把這些任務做成守護進程或者後臺服務,但這需要額外的工作量。

 linux提供了很多方法可以直接將普通的命令、腳本、應用程序以後臺的形式運行起來,這樣就不會阻塞終端窗口的繼續使用。常用的涉及後臺執行的命令有十幾多個,包括:&、ctrl+z、bg、fg、nohup、disown、setsid、(cmd)、jobs、ps、kill 等。

 下面先對每個命令的功能作用做一個簡單的介紹,然後分別給出使用案例進行詳細解釋。

1、後臺執行腳本命令功能介紹

&:將當前命令以後臺的形式運行;
ctrl+z:將前臺任務轉後臺並凍結;
bg:將後臺凍結的任務再次運行起來;
fg:將後臺任務重新轉前臺執行;
nohup:隔離終端掛斷信號,是命令的前綴;
disown:隔離終端掛斷信號,事後使用;
setsid:重新創建一個會話進程來執行任務;
(cmd):創建一個獨立shell來執行命令;
jobs:查看在後臺運行的任務列表;
ps:查看正在運行的進程信息;
kill:殺掉某個進程;

 下面就分別對上面的命令舉例來說說如何讓腳本命令在後臺執行,先看一下測試用例。

2、後臺腳本任務測試用例

 下面所有的例子中的腳本統一使用這個腳本,它的功能是每2秒打印一次當前時間。hzqtest8.sh是測試腳本的名字,.sh文件最好放在當前用戶默認目錄中(如果你放在其他目錄了,請注意權限問題!)。

1)創建腳本:

#創建腳本文件
hzq@ubuntu:~$ sudo gedit hzqtest8.sh
[sudo] hzq 的密碼:
#輸入腳本內容
#!/bin/bash
for ((i = 0; i < 10; i++)); do
    sleep 2
    echo $(date)
done
#保存退出。

2)賦予執行權限:

hzq@ubuntu:~$ sudo chmod 755 hzqtest8.sh

3、linux後臺運行命令和腳本任務的例子

 下面通過6個典型的使用案例來解釋各個命令的功能和使用方法。

● 例子1:用&

hzq@ubuntu:~$ ./hzqtest8.sh &

 功能:&加在一個命令的最後,可以把當前行的命令放在後臺執行。注意&前面有空格。

 這種方法中,當非正常退出當前shell終端時(包括直接叉掉、殺死、直接註銷關機等),後臺運行的hzqtest8.sh也會結束。這是因爲腳本在後臺運行時,運行腳本的父進程是當前shell終端進程,關閉當前shell終端時,會發送hangup掛斷信號給子進程,子進程收到hangup信號後也就退出了。

 但是,如果用exit退出,ctrl+d退出,命令可以繼續在後臺運行。

● 例子2:用nohup和&

爲了解決上面的問題可以用下面的例子,

hzq@ubuntu:~$ nohup ./hzqtest8.sh &
[1] 3640
hzq@ubuntu:~$ nohup: 忽略輸入並把輸出追加到'nohup.out'
hzq@ubuntu:~$

 功能:命令前加上nohup可以讓你退出shell之後繼續運行相應的進程。nohup就是忽略當前任務掛斷信號的意思。這樣就解決上面的問題了。

 輸入nohup命令之後會給出提示:nohup: ignoring input and appending output to ‘nohup.out’(中文版參見上文),這是正常提示,直接打回車就可以。

  • nohup默認會把標準輸出重定向到默認文件nohup.out中,你可以自定義該輸出文件,如下例子。
hzq@ubuntu:~$ nohup ./hzqtest8.sh >hzqout.txt &
[1] 3668
hzq@ubuntu:~$ nohup: 忽略輸入重定向錯誤到標準輸出端

[1]+  已完成               nohup ./hzqtest8.sh > hzqout.txt
hzq@ubuntu:~$
#看一下輸出文件裏的內容。
hzq@ubuntu:~$ cat hzqout.txt
2019年 10月 25日 星期五 23:37:48 CST
2019年 10月 25日 星期五 23:37:49 CST
2019年 10月 25日 星期五 23:37:50 CST
2019年 10月 25日 星期五 23:37:51 CST
2019年 10月 25日 星期五 23:37:52 CST
2019年 10月 25日 星期五 23:37:53 CST
2019年 10月 25日 星期五 23:37:54 CST
2019年 10月 25日 星期五 23:37:55 CST
2019年 10月 25日 星期五 23:37:56 CST
2019年 10月 25日 星期五 23:37:57 CST
  • 如果輸入nohup後不想打回車,可以用下面的例子,
hzq@ubuntu:~$ nohup ./hzqtest8.sh >hzqout.txt 2>&1 &
[1] 3690
hzq@ubuntu:~$ cat hzqout.txt
nohup: 忽略輸入
2019年 10月 25日 星期五 23:38:53 CST
2019年 10月 25日 星期五 23:38:54 CST
2019年 10月 25日 星期五 23:38:55 CST
2019年 10月 25日 星期五 23:38:56 CST
2019年 10月 25日 星期五 23:38:57 CST
2019年 10月 25日 星期五 23:38:58 CST
2019年 10月 25日 星期五 23:38:59 CST
2019年 10月 25日 星期五 23:39:00 CST
2019年 10月 25日 星期五 23:39:01 CST
2019年 10月 25日 星期五 23:39:02 CST
[1]+  已完成               nohup ./hzqtest8.sh > hzqout.txt 2>&1
hzq@ubuntu:~$

 功能解釋:2>&1 是將錯誤提示信息的輸出 重定向到 標準輸出,而這裏的標準輸出已經重定向到hzqout.txt文件,也就是說標準的錯誤提示也直接輸出到out.file文件中,所以就沒有提示了,也就不用再打回車了。

  • 另外,如果你的後臺任務沒有輸出,你可以直接重定向到/dev/null

● 例子3:用ctrl+z、jobs和bg

hzq@ubuntu:~$ ./hzqtest8.sh
2019年 10月 25日 星期五 23:56:15 CST
2019年 10月 25日 星期五 23:56:16 CST
2019年 10月 25日 星期五 23:56:17 CST
2019年 10月 25日 星期五 23:56:18 CST
^Z[3]   已完成               nohup ./hzqtest8.sh > /dev/null 2>&1

[4]+  已停止               ./hzqtest8.sh
hzq@ubuntu:~$ jobs
[4]+  已停止               ./hzqtest8.sh
hzq@ubuntu:~$ bg 4
[4]+ ./hzqtest8.sh &
hzq@ubuntu:~$ 2019年 10月 25日 星期五 23:57:04 CST
2019年 10月 25日 星期五 23:57:05 CST
2019年 10月 25日 星期五 23:57:06 CST
2019年 10月 25日 星期五 23:57:07 CST
2019年 10月 25日 星期五 23:57:08 CST
2019年 10月 25日 星期五 23:57:09 CST

[4]+  已完成               ./hzqtest8.sh
hzq@ubuntu:~$ 

 功能:上面的例子中腳本命令事先已經正常執行,然後你可能發現這個任務執行時間比較長,一直獨佔着終端窗口的使用,很不方便。

 ctrl+z命令可以將當前的前臺任務轉後臺,也就是放到後臺任務池中了,這個時候前臺窗口就變成非阻塞狀態了,但是要注意轉過去的任務在後臺默認是凍結狀態。從上面例子中可以看出任務輸出了4行之後中斷了。

 這個時候需要用到bg命令,bg命令的功能就是將後臺凍結的任務再次運行起來,但是它需要一個任務ID號,而jobs命令就是查看所有任務狀態的,包括ID號。

 例子中的bg 4就是當前任務號碼。

 該例子中沒有使用nohup,有需要的同學可以自行加上,包括重定向都是可以加上的。

● 例子4:用disown、jobs和&

 上面的例子中沒有使用nohup命令,所以當終端環境強行退出時,後臺正在執行的任務(作業/命令/程序/腳本)也會退出,由於各種原因你可能想事後加上nohup的功能(忽略終端關閉信號),看下面的例子。

hzq@ubuntu:~$ ./hzqtest8.sh >hzqout.txt 2>&1 &
[1] 7168
hzq@ubuntu:~$ jobs
[1]+  運行中               ./hzqtest8.sh > hzqout.txt 2>&1 &
hzq@ubuntu:~$ disown -h %1
hzq@ubuntu:~$ 

 功能:disown也是隔離終端掛斷信號,但主要用於事後使用。上面執行完disown之後,你可以強行關閉終端窗口,然後等待1分鐘後去查看重定向文件hzqout.txt看看有沒有執行成功,如果成功裏面有完整的10條信息,並且是連續的。下面的結果可以看到已經成功執行了。

hzq@ubuntu:~$ ps -ef |grep hzqtest
hzq        7166   7152  0 01:11 pts/1    00:00:00 grep --color=auto hzqtest
#確認後臺進程已經執行完畢退出,後面會解釋用法。
hzq@ubuntu:~$ cat hzqout.txt
2019年 10月 26日 星期六 01:11:16 CST
2019年 10月 26日 星期六 01:11:20 CST
2019年 10月 26日 星期六 01:11:24 CST
2019年 10月 26日 星期六 01:11:28 CST
2019年 10月 26日 星期六 01:11:32 CST
2019年 10月 26日 星期六 01:11:36 CST
2019年 10月 26日 星期六 01:11:40 CST
2019年 10月 26日 星期六 01:11:44 CST
2019年 10月 26日 星期六 01:11:48 CST
2019年 10月 26日 星期六 01:11:52 CST
hzq@ubuntu:~$ 

● 例子5:用setsid和&

hzq@ubuntu:~$ setsid ./hzqtest8.sh &
[1] 3001
hzq@ubuntu:~$ 2019年 10月 26日 星期六 16:27:09 CST
2019年 10月 26日 星期六 16:27:11 CST
2019年 10月 26日 星期六 16:27:13 CST
2019年 10月 26日 星期六 16:27:15 CST
2019年 10月 26日 星期六 16:27:17 CST
2019年 10月 26日 星期六 16:27:19 CST
2019年 10月 26日 星期六 16:27:21 CST
2019年 10月 26日 星期六 16:27:23 CST
2019年 10月 26日 星期六 16:27:25 CST
2019年 10月 26日 星期六 16:27:27 CST

[1]+  已完成               setsid ./hzqtest8.sh
hzq@ubuntu:~$

 功能:setsid是重新創建一個會話進程來執行任務。setsid可以起到和nohup類似的效果,但是setsid更徹底,所以嚴格上說setsid不是忽略終端關閉信號,而是這個後臺任務創建之後就與當前終端沒有關係了,所以當前終端的關閉自然不會影響到它。

 同然的原理,大家估計已經想到了,jobs命令在這個時候是不起作用的。

 另外,和nohup還有一個區別就是,不用多打一個回車,因爲它沒有提示信息。

● 例子6:用 小括號/圓括號 和&

hzq@ubuntu:~$ (./hzqtest8.sh &)
hzq@ubuntu:~$ 2019年 10月 26日 星期六 23:58:26 CST
2019年 10月 26日 星期六 23:58:28 CST
2019年 10月 26日 星期六 23:58:30 CST
2019年 10月 26日 星期六 23:58:32 CST
2019年 10月 26日 星期六 23:58:34 CST
2019年 10月 26日 星期六 23:58:37 CST
2019年 10月 26日 星期六 23:58:39 CST
2019年 10月 26日 星期六 23:58:41 CST
2019年 10月 26日 星期六 23:58:43 CST
2019年 10月 26日 星期六 23:58:45 CST
hzq@ubuntu:~$ 

 功能:小括號可以起到和setsid類似的效果,小括號是創建一個獨立shell來執行命令,當前的後臺任務創建之後就與當前終端沒有關係了,所以終端的關閉也不會影響到它。

 同然的原理,jobs命令在這個時候是不起作用的。

 另外,和setsid一樣,圓括號執行命令不用多打一個回車,因爲它沒有提示信息。

4、查看後臺任務的命令

 常用的有jobs和ps命令,區別是jobs用於查看當前終端後臺運行的任務,換了終端就看不到了(包括關閉終端再重新打開也看不到的)。而ps命令用於查看全局所有後臺進程的信息,當然可以看到別的終端運行的後臺任務。

1)jobs命令
功能:查看當前終端任務信息

hzq@ubuntu:~$ jobs -l
[1]-  3427 運行中               nohup ./hzqtest8.sh &
[2]+  3445 運行中               nohup firefox &

jobs -l選項可以多顯示一個PID信息。
第一列:任務序號,注意並不是PID。
第二列:+ 號表示當前頂部任務,- 號其次任務,沒符號是其他任務。
第三列:PID(上面例子中,默認情況下沒有PID)。
第四列:狀態,四種(運行中,已停止,已完成,已殺死)。
第五列:任務名稱(即剛纔運行的命令)。

2)ps命令
功能:全局查看進程信息

hzq@ubuntu:~$ ps -ef |grep gedit
root       3791   2566  0 00:29 pts/0    00:00:00 sudo gedit
root       3792   3791  0 00:29 pts/0    00:00:00 gedit
root       3802   2566  0 00:30 pts/0    00:00:00 sudo gedit
root       3803   3802  0 00:30 pts/0    00:00:00 gedit
hzq        3820   2566  0 00:44 pts/0    00:00:00 grep --color=auto gedit

 ps命令是Process Status的縮寫,功能比較強大,參數非常多,尤其與其他命令組合時可以完成很複雜的操作。
 ps -ef |grep hzqtest是常見用法之一,
 e:表示列出所有進程,f:表示輸出完整格式,
 grep hzqtest:表示過濾篩選“hzqtest”關鍵字。
 上面例子中,第一列:用戶名,第二列:PID,第三列:父級PID,最後一列:命令名稱或路徑

5、關閉後臺任務的命令

 處於linux後臺的任務有幾種關閉方式:任務運行完畢自行退出;通過交互方式退出(包括傳入參數對話,界面操作,終端ctrl+c等);通過進程管理工具殺掉;關閉系統退出等。

 kill命令:屬於進程管理工具,功能:殺掉進程。

hzq@ubuntu:~$ jobs
[2]   已停止               nohup firefox
[3]-  已停止               nohup sudo gedit
[4]+  已停止               nohup sudo gedit
hzq@ubuntu:~$ kill -9 %2

[2]   已停止               nohup firefox
hzq@ubuntu:~$ jobs
[2]   已殺死               nohup firefox
[3]-  已停止               nohup sudo gedit
[4]+  已停止               nohup sudo gedit
hzq@ubuntu:~$ jobs
[3]-  已停止               nohup sudo gedit
[4]+  已停止               nohup sudo gedit
  • 1)上面的例子中先通過jobs命令查看任務號,然後通過任務號%N殺死進程!最後再次查詢發現jobs中的任務已經減少了。
hzq@ubuntu:~$ ps -ef |grep gedit
root       3791   2566  0 00:29 pts/0    00:00:00 sudo gedit
root       3792   3791  0 00:29 pts/0    00:00:00 gedit
root       3802   2566  0 00:30 pts/0    00:00:00 sudo gedit
root       3803   3802  0 00:30 pts/0    00:00:00 gedit
hzq        3829   2566  0 00:59 pts/0    00:00:00 grep --color=auto gedit
hzq@ubuntu:~$ sudo kill -9 3791
[sudo] hzq 的密碼: 
[3]-  已殺死               nohup sudo gedit
hzq@ubuntu:~$ ps -ef |grep gedit
root       3792    912  0 00:29 pts/0    00:00:00 gedit
root       3802   2566  0 00:30 pts/0    00:00:00 sudo gedit
root       3803   3802  0 00:30 pts/0    00:00:00 gedit
hzq        3835   2566  0 01:01 pts/0    00:00:00 grep --color=auto gedit
  • 2)上面的例子中先通過ps命令查看任務PID,然後通過PID殺掉進程,注意上面例子中使用了管理員權限。
  • 3)如果你的任務還沒有轉到後臺運行,那麼直接Ctrl+c 就可以終止了。或者你也可以將後臺任務轉到前臺然後執行ctrl+c來終止。該方法可參考下面舉例。

6、前後臺任務的轉換

1)fg命令
功能:將後臺中的任務調至前臺並繼續運行。

hzq@ubuntu:~$ jobs
[1]-  運行中               nohup gedit &
[2]+  運行中               nohup ./hzqtest8.sh &
hzq@ubuntu:~$ fg 1
nohup gedit

先通過上面介紹的jobs命令查看任務信息,然後用fg N將選中的任務調到前臺,跳到前臺之後終端界面被阻塞,此時終端不能做別的事情了。

2)Ctrl + z 命令
功能:將正在前臺執行的命令作業放到後臺,並凍結運行狀態。

hzq@ubuntu:~$ ./hzqtest8.sh
2019年 10月 27日 星期日 01:53:31 CST
2019年 10月 27日 星期日 01:53:33 CST
^Z
[3]+  已停止               ./hzqtest8.sh
hzq@ubuntu:~$ jobs
[3]+  已停止               ./hzqtest8.sh

例子中先正常運行任務腳本,可以看到剛開始是正常輸出的,執行ctrl+z之後,提示任務已停止,用jobs查看任務已在後臺並處於停止狀態。

3)bg命令
功能:將後臺凍結的任務再次運行起來,運行後任務還在後臺。

hzq@ubuntu:~$ jobs
[1]+  已停止               ./hzqtest8.sh
hzq@ubuntu:~$ bg 1
[1]+ ./hzqtest8.sh &
hzq@ubuntu:~$ 2019年 10月 27日 星期日 01:58:17 CST
2019年 10月 27日 星期日 01:58:19 CST
2019年 10月 27日 星期日 01:58:21 CST

[1]+  已完成               ./hzqtest8.sh

上面例子中先用jobs查看有一個任務處於後臺停止狀態,執行bg 1之後任務繼續在後臺運行,並繼續輸出剩餘信息。

最後

 本文以Ubuntu18爲測試環境,其他linux版本包括centos、redhat等大多數應該是沒問題的,這些命令都是linux通用的命令,如果有細微的效果差異可能是版本和環境的問題,自己可以嘗試調整一下。

 另外screen工具也是任務管理常用的工具,它的功能也比較強大,screen是一個屏幕任務進程管理器,也可以將多個任務作業轉到後臺運行,它是第三方工具,Ubuntu標配沒有這個工具,需要另外安裝,所以這裏就不多說了,有興趣的朋友可以自己研究一下。(如果有三個以上同學留言需要screen的文章我將再寫一篇screen的使用案例介紹哈:)

 歡迎交流分享,討論補充~ ~

參考文章《Ubuntu桌面啓動後自動執行指定的命令或程序的三種方法》
參考文章《vmware虛擬機運行速度卡慢原因分析及解決辦法大全(一)》

轉載請註明本文地址:https://blog.csdn.net/davidhzq/article/details/102766881

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