讓程序在後臺可靠執行的幾種方法
簡介: 想讓程序在斷開連線後依然保持執行?如果該程序已經開始運行了該如何補救? 如果有大量這類需求如何簡化操作?
我們經常會碰到這樣的問題,用 telnet/ssh 登入了遠端的 Linux 伺服器,運行了一些耗時較長的任務, 結果卻由於網路的不穩定導致任務中途失敗。如何讓命令提交後不受本地關閉終端視窗/網路斷開連線的干擾呢?下面舉了一些例子, 您可以針對不同的場景選擇不同的方式來處理這個問題。
-----------------------------------------------------------------------------------------------
場景:
解決方法:我們知道,當用戶登出(logout)或者網路斷開時,終端會收到 HUP(hangup)訊號從而關閉其所有子程序。因此,我們的解決辦法就有兩種途徑:要麼讓程序忽略 HUP 訊號,要麼讓程序執行在新的會話裡從而成為不屬於此終端的子程序。
1. nohup
nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 訊號。讓我們先來看一下 nohup 的幫助資訊:
NOHUP(1) User Commands NOHUP(1) NAME nohup - run a command immune to hangups, with output to a non-tty SYNOPSIS nohup COMMAND [ARG]... nohup OPTION DESCRIPTION Run COMMAND, ignoring hangup signals. --help display this help and exit --version output version information and exit
可見,nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標準輸出和標準錯誤預設會被重定向到 nohup.out 檔案中。一般我們可在結尾加上"&"來將命令同時放入後臺執行,也可用">filename 2>&1"
來更改預設的重定向檔名。
[[email protected] ~]# nohup ping www.ibm.com & [1] 3059 nohup: appending output to `nohup.out' [[email protected] ~]# ps -ef |grep 3059 root 3059 9840 21:06 pts/3 00:00:00 ping www.ibm.com root 3067 984 0 21:06 pts/3 00:00:00 grep 3059 [[email protected] ~]#
2. setsid
nohup 無疑能通過忽略 HUP 訊號來使我們的程序避免中途被中斷,但如果我們換個角度思考,如果我們的程序不屬於接受 HUP 訊號的終端的子程序,那麼自然也就不會受到 HUP 訊號的影響了。setsid 就能幫助我們做到這一點。讓我們先來看一下 setsid 的幫助資訊:
SETSID(8) Linux Programmer’s Manual SETSID(8) NAME setsid - run a program in a new session SYNOPSIS setsid program [ arg ... ] DESCRIPTION setsid runs a program in a new session.
可見 setsid 的使用也是非常方便的,也只需在要處理的命令前加上 setsid 即可。
[[email protected] ~]# setsid ping www.ibm.com [[email protected] ~]# ps -ef |grep www.ibm.com root 31094 1 0 07:28 ? 00:00:00 ping www.ibm.com root 31102 29217 0 07:29 pts/4 00:00:00 grep www.ibm.com [[email protected] ~]#
值得注意的是,上例中我們的程序 ID(PID)為31094,而它的父 ID(PPID)為1(即為 init 程序 ID),並不是當前終端的程序 ID。請將此例與nohup例中的父 ID 做比較。
3.&
這裡還有一個關於 subshell 的小技巧。我們知道,將一個或多個命名包含在“()”中就能讓這些命令在子 shell 中執行中,從而擴展出很多有趣的功能,我們現在要討論的就是其中之一。
當我們將"&"也放入“()”內之後,我們就會發現所提交的作業並不在作業列表中,也就是說,是無法通過jobs
來檢視的。讓我們來看看為什麼這樣就能躲過
HUP 訊號的影響吧。
[[email protected] ~]# (ping www.ibm.com &) [[email protected] ~]# ps -ef |grep www.ibm.com root 16270 1 0 14:13 pts/4 00:00:00 ping www.ibm.com root 16278 15362 0 14:13 pts/4 00:00:00 grep www.ibm.com [[email protected] ~]#
從上例中可以看出,新提交的程序的父 ID(PPID)為1(init 程序的 PID),並不是當前終端的程序 ID。因此並不屬於當前終端的子程序,從而也就不會受到當前終端的 HUP 訊號的影響了。
-----------------------------------------------------------------------------------------------
場景:我們已經知道,如果事先在命令前加上 nohup 或者 setsid 就可以避免 HUP 訊號的影響。但是如果我們未加任何處理就已經提交了命令,該如何補救才能讓它避免 HUP 訊號的影響呢?
解決方法:這時想加 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.
可以看出,我們可以用如下方式來達成我們的目的。
-
用
disown -h jobspec
來使某個作業忽略HUP訊號。 -
用
disown -ah
來使所有的作業都忽略HUP訊號。 -
用
disown -rh
來使正在執行的作業忽略HUP訊號。
需要注意的是,當使用過 disown 之後,會將把目標作業從作業列表中移除,我們將不能再使用jobs
來檢視它,但是依然能夠用ps
-ef
查詢到它。
但是還有一個問題,這種方法的操作物件是作業,如果我們在執行命令時在結尾加了"&"來使它成為一個作業並在後臺執行,那麼就萬事大吉了,我們可以通過jobs
命令來得到所有作業的列表。但是如果並沒有把當前命令作為作業來執行,如何才能得到它的作業號呢?答案就是用
CTRL-z(按住Ctrl鍵的同時按住z鍵)了!
CTRL-z 的用途就是將當前程序掛起(Suspend),然後我們就可以用jobs
命令來查詢它的作業號,再用bg jobspec
來將它放入後臺並繼續執行。需要注意的是,如果掛起會影響當前程序的執行結果,請慎用此方法。
[[email protected] build]# cp -r testLargeFile largeFile & [1] 4825 [[email protected] build]# jobs [1]+ Running cp -i -r testLargeFile largeFile & [[email protected] build]# disown -h %1 [[email protected] build]# ps -ef |grep largeFile root 4825 968 1 09:46 pts/4 00:00:00 cp -i -r testLargeFile largeFile root 4853 968 0 09:46 pts/4 00:00:00 grep largeFile [[email protected] build]# logout
[[email protected] build]# cp -r testLargeFile largeFile2 [1]+ Stopped cp -i -r testLargeFile largeFile2 [[email protected] build]# bg %1 [1]+ cp -i -r testLargeFile largeFile2 & [[email protected] build]# jobs [1]+ Running cp -i -r testLargeFile largeFile2 & [[email protected] build]# disown -h %1 [[email protected] build]# ps -ef |grep largeFile2 root 5790 5577 1 10:04 pts/3 00:00:00 cp -i -r testLargeFile largeFile2 root 5824 5577 0 10:05 pts/3 00:00:00 grep largeFile2 [[email protected] build]#
-----------------------------------------------------------------------------------------------
場景:我們已經知道了如何讓程序免受 HUP 訊號的影響,但是如果有大量這種命令需要在穩定的後臺裡執行,如何避免對每條命令都做這樣的操作呢?
解決方法:此時最方便的方法就是 screen 了。簡單的說,screen 提供了 ANSI/VT100 的終端模擬器,使它能夠在一個真實終端下執行多個全屏的偽終端。screen 的引數很多,具有很強大的功能,我們在此僅介紹其常用功能以及簡要分析一下為什麼使用 screen 能夠避免 HUP 訊號的影響。我們先看一下 screen 的幫助資訊:
SCREEN(1) SCREEN(1) NAME screen - screen manager with VT100/ANSI terminal emulation SYNOPSIS screen [ -options ] [ cmd [ args ] ] screen -r [[pid.]tty[.host]] screen -r sessionowner/[[pid.]tty[.host]] DESCRIPTION Screen is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells). Each virtual terminal provides the functions of a DEC VT100 terminal and, in addition, several control functions from the ISO 6429 (ECMA 48, ANSI X3.64) and ISO 2022 standards (e.g. insert/delete line and support for multiple character sets). There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows moving text regions between windows.
使用 screen 很方便,有以下幾個常用選項:
-
用
screen -dmS session name
來建立一個處於斷開模式下的會話(並指定其會話名)。 -
用
screen -list
來列出所有會話。 -
用
screen -r session name
來重新連線指定會話。 -
用快捷鍵
CTRL-a d
來暫時斷開當前會話。
[[email protected] ~]# screen -dmS Urumchi [[email protected] ~]# screen -list There is a screen on: 12842.Urumchi (Detached) 1 Socket in /tmp/screens/S-root. [[email protected] ~]# screen -r Urumchi
當我們用“-r”連線到 screen 會話後,我們就可以在這個偽終端裡面為所欲為,再也不用擔心 HUP 訊號會對我們的程序造成影響,也不用給每個命令前都加上“nohup”或者“setsid”了。這是為什麼呢?讓我來看一下下面兩個例子吧。
[[email protected] ~]# ping www.google.com & [1] 9499 [[email protected] ~]# pstree -H 9499 init─┬─Xvnc ├─acpid ├─atd ├─2*[sendmail] ├─sshd─┬─sshd───bash───pstree │ └─sshd───bash───ping
我們可以看出,未使用 screen 時我們所處的 bash 是 sshd 的子程序,當 ssh 斷開連線時,HUP 訊號自然會影響到它下面的所有子程序(包括我們新建立的 ping 程序)。
[[email protected] ~]# screen -r Urumchi [ro[email protected] ~]# ping www.ibm.com & [1] 9488 [[email protected] ~]# pstree -H 9488 init─┬─Xvnc ├─acpid ├─atd ├─screen───bash───ping ├─2*[sendmail]
而使用了 screen 後就不同了,此時 bash 是 screen 的子程序,而 screen 是 init(PID為1)的子程序。那麼當 ssh 斷開連線時,HUP 訊號自然不會影響到 screen 下面的子程序了。
-----------------------------------------------------------------------------------------------
現在幾種方法已經介紹完畢,我們可以根據不同的場景來選擇不同的方案。nohup/setsid 無疑是臨時需要時最方便的方法,disown 能幫助我們來事後補救當前已經在運行了的作業,而 screen 則是在大批量操作時不二的選擇了。
相關推薦
避免後臺程序被殺死的幾種方法
Android的幾種程序 前臺程序 即與使用者正在互動的Activity或者Activity用到的Service等,如果系統記憶體不足時前臺程序是最後被殺死的。 可見程序 可以是處於暫停狀態(onPause)的Activity或者繫結在其上的Service,
讓程序在後臺可靠執行的幾種方法
簡介: 想讓程序在斷開連線後依然保持執行?如果該程序已經開始運行了該如何補救? 如果有大量這類需求如何簡化操作? 我們經常會碰到這樣的問題,用 telnet/ssh 登入了遠端的 Linux 伺服器,運行了一些耗時較長的任務, 結果卻由於網路的不穩定導致任務中途失
Linux 技巧:讓程序在後臺可靠執行的幾種方法
我們經常會碰到這樣的問題,用 telnet/ssh 登入了遠端的 Linux 伺服器,運行了一些耗時較長的任務, 結果卻由於網路的不穩定導致任務中途失敗。如何讓命令提交後不受本地關閉終端視窗/網路斷開連線的干擾呢?下面舉了一些例子, 您可以針對不同的場景選擇不同的方式來處理這
Linux 技巧:讓程序在後臺可靠執行的幾種方法&CentOS 7通過Firewall開放防火牆埠
一.讓程序在後臺可靠執行的幾種方法 方法1 #nohup 【命令】 & 例: [[email protected] ~]# nohup ping www.ibm.com & 方法2 # (【命令】 &) 例: # (ping www.i
Linux 技巧:讓進程在後臺可靠執行的幾種方法
stl 選項 con 中斷 program ng- dem 不同 正在 我們常常會碰到這種問題。用 telnet/ssh 登錄了遠程的 Linux server,執行了一些耗時較長的任務, 結果卻因為網絡的不穩定導致任務中途失敗。怎樣讓命令提交後不受本地關閉終端
讓進程在後臺可靠運行的幾種方法
讓進程在後臺可靠運行的幾種方法 nohup setsid & disown screen讓進程在後臺可靠運行的幾種方法說明:我們經常會碰到這樣的問題,用 telnet/ssh 登錄了遠程的 Linux 服務器,運行了一些耗時較長的任務, 結果卻由於網絡的不穩定導致任務中途失敗。如何讓命令提交後不受本地關閉終
Linux 讓進程在後臺可靠運行的幾種方法
lin post body nohup 所有 sid iso gpo 啟動 nohup 忽略 hang up 信號 setsid 使得父進程為1(init) & 使得父進程為1(init) disown 可以對已經啟動的進程進行忽略
nohup 讓進程在後臺可靠運行的幾種方法
AR 列表 進程 opp ron bsp HA 環境 per 1. nohup nohup 無疑是我們首先想到的辦法。顧名思義,nohup 的用途就是讓提交的命令忽略 hangup 信號。 nohup 的使用是十分方便的,只需在要處理的命令前加上 nohup 即可,標準
檢視某個程序執行時間的幾種方法
1.首先查出某個程序的pid,然後使用ps命令 [[email protected] ~]# jps 2640 Jps 2339 DataNode 2239 NameNode [[email protected] ~]# ps -p 2239 -o etime ELAPSE
Python呼叫shell命令的幾種方法(在新程序中執行shell命令)
有時候難免需要直接呼叫Shell命令來完成一些比較簡單的操作,比如mount一個檔案系統之類的。那麼我們使用Python如何呼叫Linux的Shell命令?下面來介紹幾種常用的方法: 1. os 模組 1.1. os模組的exec方法族 Python的exec系
讓Python指令碼暫停執行的幾種方法(轉載)
轉自:讓Python指令碼暫停執行的幾種方法 1.time.sleep(secs) 參考文件原文: Suspend execution for the given number of seconds. The argument may be a
根據程序控制代碼 獲得可執行檔案路徑 的幾種方法
通過程序控制代碼,獲得可執行檔案的路徑,主要有以下幾種方法: 第一種方法:也是最常用的方法,是通過GetModuleFileNameEx函式獲得可執行檔案的模組路徑,這個函式從Windows NT 4.0開始到現在的Vista系統都能使用,向後相容性比較好。 【函式
C#啟動外部程序以及等待外部程序關閉的幾種方法
string C# main 無限 完成 nbsp text enable geb 1. 啟動外部程序,不等待其退出。 2. 啟動外部程序,等待其退出。 3. 啟動外部程序,無限等待其退出。 4. 啟動外部程序,通過事件監視其退出。 // using Sy
windows下.bat程序開機自啟動的幾種方法
win 命名 set 路徑 ima 窗口 ros 自啟動 obj 以下兩種方法,親測能夠執行的1、編寫VBS腳本新建腳本script.vbs,腳本內容如下:set ws=WScript.CreateObject("WScript.Shell")ws.Ru
歸納一下:C#執行緒同步的幾種方法
我們在程式設計的時候,有時會使用多執行緒來解決問題,比如你的程式需要在後臺處理一大堆資料,但還要使使用者介面處於可操作狀態;或者你的程式需要訪問一些外部資源如資料庫或網路檔案等。這些情況你都可以建立一個子執行緒去處理,然而,多執行緒不可避免地會帶來一個問題,就是執行緒同步的問題。如果這個問題處理不好,我們就
Android中使用非同步執行緒更新UI檢視的幾種方法
在Android中子執行緒是不能更新ui的。 所以我們要通過其他方式來動態改變ui檢視, 1、runOnUiThreadactivity提供的一個輕量級更新ui的方法,在Fragment需要使用的時候要用getActivity.runOnUiThread開啟執行緒 這種方法最簡單,方便更新一些不需要判斷的
Java使用Executor執行Callable任務時的幾種方法
多執行緒在需要返回值時,我們知道需要用到Callable和Future。Callable的cell方法可以返回一個值並且可丟擲異常,是對Runnable的很好的補充;Future表示了一個任務的週期,它提供了判斷任務狀態、獲取任務結果和取消任務等方法 。 下面演示三種使用Executor執行Call
java中執行緒同步的幾種方法
方法一: 使用synchronized關鍵字 由於java的每個物件都有一個內建鎖,當用此關鍵字修飾方法時, 內建鎖會保護整個方法。在呼叫該方法前,需要獲得內建鎖,否則就處於阻塞狀態。 注: synchronized關鍵字也可以修飾靜態方法,此時如果呼叫該靜態方法,將會
多執行緒(一):建立執行緒的幾種方法
概括來說就是兩種:1、繼承Thread類,重寫run方法,然後start。不推薦這種,因為java的單繼承特性。 2、Thread類的建構函式中可以接受Runnable任務,所以只要是Runnable例項就可以作為引數給Thread 一般有兩種建立Runnable例項的方法(1)實現Runn
asp執行sql語句、儲存過程的幾種方法
使用connection物件 會返回一個關閉的recordset記錄集,此記錄集不要再次宣告關閉 建議在update、insert、delete時使用 strCon="provider=sqloledb;data source=servername;initial catalog