1. 程式人生 > >nohup與&區別和命令執行輸出重定向

nohup與&區別和命令執行輸出重定向

開發十年,就只剩下這套架構體系了! >>>   

1、nohup與&的區別

測試程式碼如下:

 

是一個輸出hello與迴圈輪數的死迴圈程式,每輸出一行就休眠1秒。

使用 ./a.out 前臺執行程式,會是什麼效果呢?


程式每隔一秒會在終端輸出一個字串。

此時如果鍵入Ctrl+C ,程式會收到一個SIGINT訊號,如果不做特殊處理,程式的預設行為是終止

(如上圖)。

 

使用 ./a.out& 後臺執行程式,會是什麼效果呢?


如上圖:

  • 首先會在終端顯示程序號是32389
  • 鍵入Ctrl + C,發出SIGINT訊號,程式會繼續執行

ps確認一下,確認程序依然在執行,程序號是32389。

此時如果關掉session,程式會收到一個SIGHUP訊號,此時會怎麼樣呢?

ps再次確認,可以看到關閉session之後,程序號是32389的a.out程序也關閉了

使用nohup ./a.out 又會是什麼效果呢?

使用nohup 執行程式a.out,會發現:

  • 前臺沒有出現程序號
  • 有一個“忽略輸入,輸出至nohup.out”的提示
  • hello的輸出也沒有出現在前臺

手動ps看程序號,這次a.out的程序號是32437。

 

此時如果關掉session,程式會收到一個SIGHUP訊號,程式會不會關閉呢?

關掉session後,再次ps看一下,ID為32437的a.out程序還在


這些只能通過kill把程式幹掉了,killall之後,ps檢視程序已經關閉。


killall之後,檢視發現多了一個nohup.out檔案,不過這個檔案的大小是0,有點奇怪,啟動程式的時候,明明提示了“appending output to nohup.out”呀,先把問題遺留在這,測試一下Ctrl +C。

仍如上圖,使用nohup啟動a.out,如果鍵入Ctrl+C ,程式收到SIGINT訊號後,直接關閉了

 

最後測試一下nohup和&同時使用,即用nohup./a.out &執行程式,又會是什麼效果呢?

使用nohup ./a.out &執行程式後,可以看到:

  • 會在終端顯示程序號是32524
  • 也會有一個“忽略輸入,輸出至nohup.out”的提示

 

鍵入Ctrl + C,傳送SIGINT訊號,似乎沒反應。

關閉session,傳送SIGHUP訊號,再來看看。

ID為32524的程序依然存在,後續也只能用kill來關閉它。

 

結論

使用&後臺執行程式:

  1. 結果會輸出到終端
  2. 使用Ctrl + C傳送SIGINT訊號,程式免疫
  3. 關閉session傳送SIGHUP訊號,程式關閉

 

使用nohup執行程式:

  1. 結果預設會輸出到nohup.out
  2. 使用Ctrl + C傳送SIGINT訊號,程式關閉
  3. 關閉session傳送SIGHUP訊號,程式免疫

 

平日線上經常使用nohup和&配合來啟動程式:

  • 同時免疫SIGINT和SIGHUP訊號 

同時,還有一個最佳實踐:

  • 不要將資訊輸出到終端標準輸出,標準錯誤輸出,而要用日誌元件將資訊記錄到日誌裡

 

疑問:

nohup啟動a.out,程式終止後,為啥nohup.out的大小是0?“hello”的字串哪去了?

2、命令執行輸出重定向


linux重定向及nohup不輸出的方法:

一、linux重定向:

0、1和2分別表示標準輸入、標準輸出和標準錯誤資訊輸出,可以用來指定需要重定向的標準輸入或輸出。

在一般使用時,預設的是標準輸出,既1

當我們需要特殊用途時,可以使用其他標號。例如,將某個程式的錯誤資訊輸出到log檔案中:./program 2>log。這樣標準輸出還是在螢幕上,但是錯誤資訊會輸出到log檔案中。

另外,也可以實現0,1,2之間的重定向。

2>&1 將錯誤資訊重定向到標準輸出。

Linux下還有一個特殊的檔案/dev/null,它就像一個無底洞,所有重定向到它的資訊都會消失得無影無蹤。這一點非常有用,當我們不需要回顯程式的所有資訊時,就可以將輸出重定向到/dev/null。

如果想要正常輸出和錯誤資訊都不顯示,則要把標準輸出和標準錯誤都重定向到/dev/null, 例如:

ls 1>/dev/null 2>/dev/null

還有一種做法是將錯誤重定向到標準輸出,然後再重定向到 /dev/null,例如:

ls >/dev/null 2>&1

注意:此處的順序不能更改,否則達不到想要的效果,此時先將標準輸出重定向到 /dev/null,然後將標準錯誤重定向到標準輸出,由於標準輸出已經重定向到了/dev/null,因此標準錯誤也會重定向到/dev/null,於是一切靜悄悄:-)

由於使用nohup時,會自動將輸出寫入nohup.out檔案中,如果檔案很大的話,nohup.out就會不停的增大,這是我們不希望看到的,因此,可以利用/dev/null來解決這個問題。

(1)捨棄標準輸出,將錯誤輸出到log檔案中

nohup node bin/www >/dev/null 2>log &

(2)如果錯誤資訊也不想要的話:

nohup node bin/www >/dev/null 2>&1 &

注:其中node bin/www是專案node啟動

二、關於重定向

1. 基本概念

a、I/O重定向通常與 FD有關,shell的FD通常為10個,即 0~9;(FD:file descripter,檔案描述符)

b、常用FD有3個,為: 0(stdin,標準輸入)、1(stdout,標準輸出)、2(stderr,標準錯誤輸出),預設與keyboard、monitor、monitor有關;

c、用 < 來改變讀進的資料通道(stdin),使之從指定的檔案讀進;

d、用 > 來改變送出的資料通道(stdout, stderr),使之輸出到指定的檔案;

e、0 是 < 的預設值,因此 < 與 0<是一樣的;同理,> 與 1> 是一樣的;

f、在IO重定向 中,stdout 與 stderr 的管道會先準備好,才會從 stdin 讀進資料;

g、管道“|”(pipe line):上一個命令的 stdout 接到下一個命令的 stdin;

h、tee 命令是在不影響原本 I/O 的情況下,將 stdout 複製一份到檔案去;

i、bash(ksh)執行命令的過程:分析命令-變數求值-命令替代(``和$( ))-重定向-萬用字元展開-確定路徑-執行命令;

j、( )  將 command group 置於 sub-shell 去執行,也稱 nested sub-shell,它有一點非常重要的特性是:繼承父shell的Standard input, output, and error plus any other open file descriptors。

k、exec 命令:常用來替代當前 shell 並重新啟動一個 shell,換句話說,並沒有啟動子 shell。使用這一命令時任何現有環境都將會被清除,。exec 在對檔案描述符進行操作的時候,也只有在這時,exec 不會覆蓋你當前的 shell 環境。

2. 基本IO

cmd > file              把 stdout 重定向到 file 檔案中

cmd >> file             把 stdout 重定向到 file 檔案中(追加)

cmd 1> fiel             把 stdout 重定向到 file 檔案中

cmd > file 2>&1         把 stdout 和 stderr 一起重定向到 file 檔案中

cmd 2> file             把 stderr 重定向到 file 檔案中

cmd 2>> file            把 stderr 重定向到 file 檔案中(追加)

cmd >> file 2>&1        把 stderr 和 stderr 一起重定向到 file 檔案中

cmd < file >file2       cmd 命令以 file 檔案作為 stdin,以 file2 檔案作為 stdout

cat <>file              以讀寫的方式開啟 file

cmd < file              cmd 命令以 file 檔案作為 stdin

cmd << delimiter        Here document,從 stdin 中讀入,直至遇