nohup命令_后台任务与nohup命令
在 Linux 的終端中運行某些命令時,我們往往希望讓它們在后臺運行穩定運行而不受本地關閉終端窗口或網絡斷開連接的干擾。
先來了解一下:當用戶注銷(logout)或者網絡斷開時,終端會收到 SIGHUP 信號從而關閉其所有子進程。即 用戶準備退出 session 時,系統向該 session 發出SIGHUP信號,session 將SIGHUP信號發給所有子進程,子進程收到SIGHUP信號后,自動退出。
首發于:
后臺任務與nohup命令?www.thisfaner.com因此,要讓命令在后臺運行穩定的運行有兩種途徑:
- 讓進程忽略 SIGHUP 信號;我們可以使用 nohup 命令或 disown 命令,同時配合 & 一起使用。
- 或讓進程運行在新的會話里從而成為不屬于此終端的子進程;我們可以使用 setsid 命令
如果你不想看完全文,那么只需記住下面這兩個最常用的方法即可,其中 command 表示你要在后臺穩定運行的命令:
# 直接使用 nohub nohup Command & # 或同時重定向標準輸出和標準錯誤到 myout.file nohup Command > myout.file 2>&1 &使用 & 開啟后臺任務
在類UNIX系統的命令行模式下,用戶可使用 & 操作符以啟動進程并使之運行于后臺。
但后臺任務繼承當前 session(對話,就是終端窗口)的標準輸出(stdout)和標準錯誤(stderr);因此,后臺任務的所有輸出依然會同步地在命令行下顯示。但它不再繼承當前session的標準輸入(stdin)。
對比后面見到的守護進程的創建要求,可以看出單單使用 & 是不能保證命令在各類場景中一直在后臺穩定運行的。前后臺進程的切換:
- 按 ctrl + z將當前進程掛起到后臺暫停運行
- 【可選】通過jobs命令來得到所有作業的任務號
- 用 bg 來將掛起的進程放在后臺繼續運行
- 用 fg 來將后臺作業(在后臺運行的或者在后臺掛起的作業)放到前臺終端運行。
后臺進程的進程組ID(即PGID)與控制終端進程組ID(即TPGID)不同,因而也可以此辨識后臺進程。我們可以驗證一下:
# 同時顯示:進程ID(PID),父進程ID(PPID),進程組ID(PGID),終端進程組ID(TPGID),會話ID(SID),進程名稱 ps xao pid,ppid,pgid,tpgid,sid,comm# 下面是終端三的顯示結果 和 相關備注: ####################################### # 終端一: 運行 ping baidu.com & 10215 10071 10215 10215 10215 zsh 10703 10215 10703 10215 10215 ping # 第三列和第四列 10703 10215 并不相同 # 終端二: 運行 ping baidu.com 10723 10071 10723 10762 10723 zsh 10762 10723 10762 10762 10723 ping # 終端三: 運行 ps xao pid,ppid,pgid,tpgid,sid,comm 10393 10071 10393 10769 10393 zsh 10769 10393 10769 10769 10393 psdisown命令
disown命令。它可以將指定任務從"后臺任務” 列表(jobs命令的返回結果)之中移除。一個 “后臺任務” 只要不在這個列表之中,session 就肯定不會向它發出SIGHUP信號。
命令示例:
# 移出最近一個正在執行的后臺任務 disown # 移出所有正在執行的后臺任務 disown -r # 移出所有后臺任務 disown -a # 不移出后臺任務,但是讓它們不會收到SIGHUP信號 disown -h # 根據jobId,移出指定的后臺任務 disown %2 disown -h %2disown -ah disown -rh用法:
- 如果提交命令時已經用 & 將命令放入后臺運行,則可以直接使用 disown,比如:
- 如果提交命令時未使用 & 將命令放入后臺運行,可使用 CTRL-z 和 bg 將其放入后臺,再使用 disown
注意:
使用disown命令之后,還有一個問題。那就是,退出 session 以后,如果后臺進程與標準I/O有交互,它還是會掛掉。
這是因為"后臺任務"的標準 I/O 繼承自當前 session,disown命令并沒有改變這一點。一旦"后臺任務"讀寫標準 I/O,就會發現它已經不存在了,所以就報錯終止執行。
為了解決這個問題,需要對"后臺任務"的標準 I/O 進行重定向。比如:
node server.js > stdout.txt 2> stderr.txt < /dev/null & disownnohup 命令
還有比disown更方便的命令,就是nohup。
nohup 的原理:
- 阻止SIGHUP信號發到這個進程。
- 關閉標準輸入。該進程不再能夠接收任何輸入,即使運行在前臺。
- 重定向標準輸出和標準錯誤到當前目錄的nohup.out文件。
也就是說,nohup命令實際上將子進程與它所在的 session 分離了。
注意,nohup命令不會自動把進程變為"后臺任務”,所以必須加上&符號。
常見的兩種用法:
nohup Command & nohup Command > myout.file 2>&1 &setsid 命令
如果我們的進程不屬于接受 SIGHUP 信號的終端的子進程,那么自然也就不會受到 SIGHUP 信號的影響了。setsid 就能幫助我們做到這一點。
用法:也只需在要處理的命令前加上 setsid 即可。示例:
setsid ping www.ibm.com另可參考下文中 setsid 函數的作用。補充:各種任務
- 前臺任務(foreground job)是獨占命令行窗口的任務,只有運行完了或者手動中止該任務,才能執行其他命令。
- 后臺任務(background job),是一種在不需用戶干預的情況下運行于操作系統后臺的任務。后臺任務繼承當前 session(對話,就是終端窗口)的標準輸出(stdout)和標準錯誤(stderr);因此,后臺任務的所有輸出依然會同步地在命令行下顯示。但它不再繼承當前session的標準輸入(stdin)。
- 守護進程(daemon)是 Linux 中的后臺服務進程,它是一個特殊的孤兒進程,這種進程脫離終端,這使得它可以避免進程被任何終端所產生的信息所打斷,其在執行過程中的信息也不在任何終端上顯示。守護進程程序的名稱通常以字母"d"結尾。
守護進程的創建步驟:
- 創建子進程,終止父進程。使得程序以僵尸進程形式運行,在形式上做到了與控制終端的脫離。
- 在子進程中創建新會話(最重要)。需要使用系統函數 setsid() ,該函數的三個作用:讓進程擺脫原會話的控制、讓進程擺脫原進程組的控制和讓進程擺脫原控制終端的控制。
在調用fork函數時,子進程全盤拷貝父進程的會話期(session,是一個或多個進程組的集合)、進程組、控制終端等,雖然父進程退出了,但原先的會話期、進程組、控制終端等并沒有改變,因此,那還不是真正意義上使兩者獨立開來。setsid函數能夠使進程完全獨立出來,從而脫離所有其他進程的控制。 - 改變工作目錄
- 重設文件創建掩碼
- 關閉文件描述符
補充:命令的重定向
先看下面兩個示例:
command > /dev/null command > /dev/null 2>&1- /dev/null :代表空設備文件,寫入到它的內容都會被丟棄。
- > :代表重定向到哪里,例如:echo “123” > /home/123.txt
- 0 : 表示標準輸入 (STDIN)
- 1 :表示標準輸出(STDOUT),系統默認值是1,所以 >/dev/null 等同于1>/dev/null
- 2 :表示標準錯誤輸出(STDERR)
- & :表示等同于的意思,2>&1,表示2的輸出重定向等同于1
cmd >a 2>a 和 cmd >a 2>&1 為什么不同?
- cmd >a 2>a :stdout和stderr都直接送往文件 a ,a文件會被打開兩遍,由此導致stdout和stderr互相覆蓋。
- cmd >a 2>&1 :stdout直接送往文件a ,stderr是繼承了FD1的管道之后,再被送往文件a 。a文件只被打開一遍,就是FD1將其打開。
補充:ps命令
ps 命令的基本用法:
ps (Unix) - 維基百科ps程序(“process status"的簡稱)可以顯示當前運行的進程。一個相關的Unix工具top則可以查看運行進程的實時信息
ps有很多選項。在支持SUS和POSIX標準的操作系統上,ps常以選項-ef運行,其中”-e"選擇每一個(every)進程,"-f"指定"完整”(full)輸出格式。這些系統上的另一個常見選項是-l,它指定"長”(long)輸出格式。
由于歷史原因,大多數源自BSD的系統無法接受SUS和POSIX的標準選項(例如,“e"或”-e"選項將顯示環境變量)。在這樣的系統中,ps常使用輔助非標準選項aux,其中"a"列出了一個終端上的所有進程,包括其他用戶運行的,“x"列出所有沒有控制終端的進程,“u"添加了一列顯示每個進程的控制用戶。需要注意的是,為了最大的兼容性,使用此語法時"aux"前沒有”-"。此外,在aux之后添加"ww"可以顯示進程的完整信息,包括所有的參數,例如"ps auxww”。
示例:
$ps # ps命令和grep結合 ps -A | grep firefox-bin # 或直接使用pgrep pgrep -l firefox-bin # 查看以root用戶運行的進程 ps -U root -u如何查看守護進程?
使用 ps axj :
- a 表示不僅列當前用戶的進程,也列出所有其他用戶的進程
- x 表示不僅列有控制終端的進程,也列出所有無控制終端的進程
- j 表示列出與作業控制相關的信息
從上面命令的結果中可以發現一些 守護進行特點:
- 守護進程基本上都是以超級用戶啟動( UID 為 0 )
- 沒有控制終端( TTY 為 ?)
- 終端進程組 ID 為 -1 ( TPGID 表示終端進程組 ID)
參考
- Linux 技巧:讓進程在后臺運行更可靠的幾種方法
- Linux 守護進程的啟動方法
- 守護進程
- ps (Unix) - 維基百科
總結
以上是生活随笔為你收集整理的nohup命令_后台任务与nohup命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CoffeeScript简介 <一
- 下一篇: 荣耀万飚:预计今年下半年折叠屏手机有翻倍