我試圖理解該dd
程式的線上幫助頁,其中提到:
向正在運行的「dd」程序發送 USR1 訊號,使其將 I/O 統計資訊列印到標準錯誤,然後恢復複製。
$ dd if=/dev/zero of=/dev/null& pid=$! $ kill -USR1 $pid; sleep 1; kill $pid
這是什麼pid=$!
意思?
這是一個變數的賦值,它會取得 pid 嗎dd
?並最終用在$pid
變數中?
另外他們為什麼要用sleep
and kill
?
這是使用方法嗎-USR1
?
答案1
dd if=/dev/zero of=/dev/null&
尾隨&
意味著在後台運行前綴命令。 (免責聲明:這是過於簡單化的陳述)
參考這:
$!是最近的後台命令的PID。
所以pid=$!
分配最近的後台PID到變數pid,即dd
PID。
還有為什麼他們要使用睡眠和殺戮?
你需要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
為後台。dd
當dd
收到此訊號時,它會列印出當前進度(讀取和寫入的資料量)並繼續複製。
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)命令是pkill
和killall
,當您想按名稱尋找進程時。
答案3
對於大多數或所有 shell,$!
是 shell 分叉的最後一個進程的進程 ID(也稱為 PID)。此dd
指令使用 進行分叉&
,以便pid=$!
分叉後的右側將進程 IDdd
指派dd
給 shell 變數pid
。
進程 ID 是 Linux 或 Unix 用來指稱其中執行某些程式碼的位址空間的數字。
該kill
程式的名稱不直觀,因為其目的是向進程發送訊號(小型非同步訊息)。訊號只有幾個,大概有128個,都有編號和名稱。例如,「kill」訊號是數字 9。 USR1 被定義為編號kill -USR1 $pid
10 $pid
。dd
有時需要很長時間才能執行,因此幾乎可以肯定這是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 上的其他實現。