So verwenden/senden Sie Signale in der Befehlszeile für jedes Programm (z. B. dd)

So verwenden/senden Sie Signale in der Befehlszeile für jedes Programm (z. B. dd)

Ich versuche, die Manpage des ddProgramms zu verstehen, in der Folgendes erwähnt wird:

Wenn Sie ein USR1-Signal an einen laufenden „dd“-Prozess senden, druckt dieser die E/A-Statistiken in die Standardfehlerausgabe und setzt anschließend den Kopiervorgang fort.

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

Was pid=$!bedeutet?

Handelt es sich hier um die Zuweisung einer Variable, welche die PID von erhält und ggf. in der Variable ddverwendet wird ?$pid

Und warum verwenden sie sleepund kill?

Ist das die richtige Verwendungsweise -USR1?

Antwort1

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

Das nachfolgende Zeichen &bedeutet, dass der Präfixbefehl im Hintergrund ausgeführt wird. (Haftungsausschluss: Dies ist eine stark vereinfachte Aussage.)

Beziehen aufDas:

$! ist die PID des letzten Hintergrundbefehls.

Weisen Sie also pid=$!dieNeuester Hintergrund-PIDzur Variablen pid, also ddPID.

Und warum verwenden sie „Sleep and Kill“?

Du brauchstkill $pid (wenn kein Parameter angegeben ist, ist das Standardsignal für Kill TERM, also die Beendigung des Prozesses)um den ddProzess nach Abschluss des Tests zu beenden, da ddder Prozess sonst möglicherweise im Hintergrund weiterläuft und Ihre CPU-Ressourcen erschöpft. Überprüfen Sie dazu den Systemmonitor Ihrer Plattform.

Während Kill -USR1 $pidE/A-Statistiken gedruckt werden, wird der Prozess dadurch nicht beendet.

Ohne 1 Sekunde Schlaf ddkann Ihr Prozess durch die letzte Befehlsanweisung kill $pid** beendet werden, bevor Sie die Möglichkeit haben, Statistiken in Ihr Terminal zu schreiben. Der Prozess ist synchron, aberTrap+Write-Vorgang( kill -USR1 $pid) kann langsamer sein alsVorgang beenden( kill $pid). sleep 1Verzögern Sie daher den Start des Druckvorgangs, kill $pidum sicherzustellen, dass die Statistikausgabe abgeschlossen ist.

So wird -USR1 verwendet?

Nur man dd:

Wenn Sie ein USR1-Signal an einen laufenden „dd“-Prozess senden, druckt dieser die E/A-Statistiken in die Standardfehlerausgabe und setzt anschließend den Kopiervorgang fort.

Und man 7 signal:

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

Kombinieren Sie beide Aussagen, sollten Sie verstehen, USR1 istBenutzerdefiniertes SignalDies ist definiert durch dddie Möglichkeit für den Benutzer, es zu unterbrechen undE/A-Statistiken druckenim laufenden Betrieb. Es handelt sich um einen programmspezifischen Handler, das heißt nicht, dass Sie kill -USR1 other_program_pideine Statistikausgabe erwarten können.

Das könnte Sie auch interessierendies: Warum führt SIGUSR1 dazu, dass der Prozess beendet wird?.

Antwort2

Dies ist nur eine Demonstration, um die Verwendung des USR1Signals mit zu veranschaulichen dd.

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

startet ddim Hintergrund und kopiert Daten von /dev/zero(wobei jedes Mal, wenn ein Programm davon liest, Nullen erzeugt werden) nach /dev/null(wobei alles verworfen wird, was dorthin geschrieben wird). Dies stellt eine harmlose Instanz dar, ddmit der man experimentieren kann – sie verbraucht keinen Speicher und läuft so lange weiter, wie wir es möchten, sodass der Benutzer Zeit hat, Signale dorthin zu senden.

pid=$!

speichert die Prozesskennung des letzten Hintergrundbefehls ( $!) in der Variable pid.

kill -USR1 $pid

sendet das Signal an den Prozess, dessen Kennung der in der Variable USR1gespeicherte Wert ist , in diesem Fall der Hintergrund. Wenn dieses Signal empfangen wird, druckt es seinen aktuellen Fortschritt aus (die Menge der gelesenen und geschriebenen Daten) und fährt mit dem Kopieren fort.piddddd

sleep 1

wartet eine Sekunde.

kill $pid

sendet das TERMSignal an dd, was ddzum Beenden führt. (Es hat hier keinen Sinn, den Hintergrund ddlaufen zu lassen.)

Es wäre aufschlussreicher, dies anstelle der zweiten Zeile oben auszuführen:

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

Dadurch wird der Fortschritt zweimal mit einer Sekunde dazwischen ausgegeben, um ddden Fortschritt anzuzeigen. Anschließend wird ddohne Warten beendet.

Für die tatsächliche Verwendung würden Sie die entsprechenden Ein- und Ausgaben für den ursprünglichen ddBefehl und wahrscheinlich auch einige andere Optionen angeben. Und Sie würden den letzten Befehl nicht ausführen, killsondern warten, bis dder von selbst beendet wird.

Um Ihre letzte Frage zu beantworten, so senden Sie USR1Signale von einer Shell (oder jedes andere Signal): Sie verwendenkillmit dem Signal, das Sie senden möchten, und den Prozesskennungen (oder Jobkennungen) der Prozesse, an die Sie das Signal senden möchten. Andere (nicht-POSIX-)Befehle, die Sie verwenden können, sindpkillUndkillall, wenn Sie Prozesse nach Namen suchen möchten.

Antwort3

Bei den meisten oder allen Shells $!ist die Prozess-ID (auch PID genannt) des letzten Prozesses, den die Shell geforkt hat. Der ddBefehl wurde mit geforkt &, sodass pid=$!direkt nach dem Forken die Prozess-ID der Shell-Variable ddzugewiesen wird .ddpid

Eine Prozess-ID ist eine Nummer, die von Linux oder Unix verwendet wird, um auf einen Adressraum zu verweisen, in dem Code ausgeführt wird.

Das killProgramm hat einen nicht sehr intuitiven Namen, da sein Zweck darin besteht, Signale (kleine, asynchrone Nachrichten) an Prozesse zu senden. Es gibt nur wenige Signale, vielleicht 128 insgesamt, sie haben sowohl Nummern als auch Namen. Das „Kill“-Signal ist beispielsweise die Nummer 9. USR1 ist als Nummer 10 definiert. Daher kill -USR1 $pidsendet das Programm das Signal 10 an den Prozess mit der Nummer $pid. ddDie Ausführung dauert manchmal sehr lange, daher ist dies mit ziemlicher Sicherheit die Prozess-ID des ddBefehls, der zuvor geforkt und im Hintergrund ausgeführt wurde. Der kill $pidBefehl sendet ein TERM-Signal an dieselbe Prozess-ID. TERM bedeutet „Beenden“. Gut geschriebene Programme fangen TERM normalerweise ab, bereinigen die zugewiesenen Ressourcen und beenden dann.

ddIch bin mir nicht ganz sicher, warum Sie im Hintergrund laufen , ein USR1-Signal senden, 1 Sekunde warten und dann ddalle Ressourcen freigeben und beenden. Das gesamte Codefragment scheint anzunehmen, dass ddes lange läuft, was aber nicht stimmen kann. Ich denke, in diesem Code gibt es Race Conditions, und unabhängig von der gewünschten Semantik werden Sie diese möglicherweise nicht erhalten.

Antwort4

Wenn Sie erwarten, dddass der Befehl im Vordergrund ausgeführt wird und den aktuellen Fortschrittsstatus anzeigt, versuchen Sie, den Befehl mit status=progressdem Flag auszuführen:

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

Dadurch wird der Fortschritt dynamisch angezeigt.

Dies ist eine Erweiterung der GNU-Implementierung dd(hinzugefügt in Version 8.24, veröffentlicht im Jahr 2015), die auch in der ddImplementierung auf FreeBSD seit 12.0 (2018) verfügbar ist, aber im Allgemeinen nicht in anderen Implementierungen, einschließlich auf anderen BSDs.

verwandte Informationen