如何在任何程式的命令列中使用/發送訊號(例如 dd)

如何在任何程式的命令列中使用/發送訊號(例如 dd)

我試圖理解該dd程式的線上幫助頁,其中提到:

向正在運行的「dd」程序發送 USR1 訊號,使其將 I/O 統計資訊列印到標準錯誤,然後恢復複製。

         $ dd if=/dev/zero of=/dev/null& pid=$!
         $ kill -USR1 $pid; sleep 1; kill $pid

這是什麼pid=$!意思?

這是一個變數的賦值,它會取得 pid 嗎dd?並最終用在$pid變數中?

另外他們為什麼要用sleepand kill

這是使用方法嗎-USR1

答案1

dd if=/dev/zero of=/dev/null&

尾隨&意味著在後台運行前綴命令。 (免責聲明:這是過於簡單化的陳述)

參考:

$!是最近的後台命令的PID。

所以pid=$!分配最近的後台PID到變數pid,即ddPID。

還有為什麼他們要使用睡眠和殺戮?

你需要kill $pid (如果沒有指定參數,kill的預設訊號是TERM,即進程終止)dd完成測試後終止進程,否則dd進程可能會停留在背景並耗盡您的 CPU 資源。檢查您平台的系統監視器以查看。

雖然Kill -USR1 $pid列印 I/O 統計訊息,但它不會終止進程。

如果沒有睡眠 1 秒,您的進程可能會在有機會將統計輸出寫入終端機之前dd被最後一個命令語句 ** 終止。kill $pid這些過程是同步的,但是陷阱+寫入操作( kill -USR1 $pid) 可能慢於終止操作( kill $pid)。所以sleep 1第二要延遲啟動,kill $pid以確保統計輸出完成列印。

這就是-USR1的使用方法嗎?

只是man dd

向正在運行的「dd」程序發送 USR1 訊號,使其將 I/O 統計資訊列印到標準錯誤,然後恢復複製。

man 7 signal

   SIGUSR1   30,10,16    Term    User-defined signal 1
   SIGUSR2   31,12,17    Term    User-defined signal 2

結合這兩個陳述,你應該明白 USR1 是使用者定義訊號它的定義是dd為用戶提供一種中斷它的方法並且列印 I/O 統計訊息在飛行中。它是程序特定的處理程序,並不意味著您可以kill -USR1 other_program_pid並期望統計輸出。

您可能還感興趣this: 為什麼 SIGUSR1 會導致進程終止?

答案2

這只是一個演示,以說明USR1訊號的使用dd

dd if=/dev/zero of=/dev/null &

dd從後台開始,將資料從/dev/zero(每當程式讀取時產生零)複製到/dev/null(丟棄寫入其中的任何內容)。這提供了一個dd可用於實驗的無害實例——它不會佔用任何儲存空間,並且只要我們想要它就會繼續運行,這讓用戶有時間向它發送訊號。

pid=$!

將最後一個後台命令 () 的進程標識符儲存$!在變數中pid

kill -USR1 $pid

將訊號傳送USR1到進程,該進程的識別碼是儲存在變數中的值,在本例中pid為後台。dddd收到此訊號時,它會列印出當前進度(讀取和寫入的資料量)並繼續複製。

sleep 1

等一秒鐘。

kill $pid

發送TERM訊號至dd,導致dd退出。 (讓後台運行在這裡是沒有意義的dd。)

運行這個而不是上面的第二行會更有指導意義:

kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid

這將輸出進度兩次,中間間隔一秒,以顯示dd進度;然後dd不等就殺掉。

對於實際使用,您需要為原始dd命令指定適當的輸入和輸出,可能還有其他一些選項,並且您不會運行最後一個kill- 您會等待dd其自行完成。

USR1要回答您的最後一個問題,這就是從 shell(或任何其他訊號)發送訊號的方式:您使用kill包含要傳送的訊號以及要將訊號傳送到的進程的進程識別碼(或作業標識符)。您可以使用的其他(非 POSIX)命令是pkillkillall,當您想按名稱尋找進程時。

答案3

對於大多數或所有 shell,$!是 shell 分叉的最後一個進程的進程 ID(也稱為 PID)。此dd指令使用 進行分叉&,以便pid=$!分叉後的右側將進程 IDdd指派dd給 shell 變數pid

進程 ID 是 Linux 或 Unix 用來指稱其中執行某些程式碼的位址空間的數字。

kill程式的名稱不直觀,因為其目的是向進程發送訊號(小型非同步訊息)。訊號只有幾個,大概有128個,都有編號和名稱。例如,「kill」訊號是數字 9。 USR1 被定義為編號kill -USR1 $pid10 $piddd有時需要很長時間才能執行,因此幾乎可以肯定這是dd先前分叉並在背景運行的命令的進程 ID。該kill $pid指令向相同進程 ID 發送 TERM 訊號。 TERM 的意思是「終止」。編寫良好的程式通常會捕獲 TERM,清理它們分配的資源,然後退出。

我不完全確定為什麼你會dd在後台運行,向其發送 USR1 信號,等待 1 秒,然後導致dd釋放所有資源,然後退出。整個程式碼片段似乎假設dd運行很長時間,這可能不是真的。我認為這段程式碼中存在競爭條件,無論想要什麼語義,您可能實際上都無法獲得它們。

答案4

如果您希望dd命令在前台運行並顯示當前進度狀態。嘗試使用status=progress標誌運行命令:

sudo dd if=/dev/sda of=/dev/sdb status=progress

這將動態顯示進度。

這是 GNU 實現的擴展dd(在 2015 年發布的 8.24 版本中添加),dd自 12.0 (2018) 起也可用於 FreeBSD 上的實現,但通常不包括其他 BSD 上的其他實現。

相關內容