Shell: Ist es möglich, einen Befehl zu verzögern, ohne `sleep` zu verwenden?
21
Gibt es Ersatz, Alternativen oder Bash-Tricks, um Befehle zu verzögern, ohne sie zu verwenden sleep? Führen Sie beispielsweise den folgenden Befehl aus, ohne den Energiesparmodus tatsächlich zu verwenden:
Es gibt keinen anderen Grund als Neugier. Ich dachte, es wäre interessant, alternative Lösungen zu lernen. Ich denke, es atkönnte eines sein, aber ich konnte keine Verwendungsbeispiele finden.
User321697
1
@ user321697 "at" dient zum Planen einzelner Jobs. Sie werden vom atd-Dienst ausgeführt, sodass Ihr Shell-Skript nicht angehalten wird. Ein Anwendungsfall für at wäre, es zu einem bestimmten Zeitpunkt (asynchron) ausführen zu lassen und eine Markierungsdatei zu erstellen, wenn sie fertig ist, während Ihr Skript darauf wartet, dass diese Datei in einer while-Schleife angezeigt wird. Sie können einen ähnlichen Effekt erzielen, indem Sie einen Job so planen, dass er Ihrem Skript ein SIGCONT sendet, und dann Ihr Skript einfrieren, indem Sie sich ein SIGSTOP senden.
Grega Bremec
1
Ich bin hierher gekommen und habe erwartet, dass jeder einen Spinlock vorschlägt. Ich bin angenehm überrascht von all den Antworten.
Daan van Hoek
3
Re: „Curiosity“ - in unix.stackexchange.com/help/dont-ask , beachten Sie die Anforderung , dass „Sie nur praktisch, beantwortbar Fragen stellen sollte , basierend auf tatsächlichen Probleme , die Sie Gesicht. “ - dass dies war gut Trotz Kontroverse erhalten, macht diese Richtlinie eine eher seltene Ausnahme.
Charles Duffy
Antworten:
17
Sie haben Alternativen zu sleep: Sie sind atund cron. Im Gegensatz dazu sleepmüssen Sie den Zeitpunkt angeben, zu dem sie ausgeführt werden sollen.
Stellen Sie sicher, dass der atdDienst ausgeführt wird, indem Sie ausführen service atd status.
Angenommen, das Datum ist 11:17 Uhr UTC. Wenn Sie einen Befehl , um 11:25 UTC ausführen müssen, ist die Syntax: echo "This is a test" | at 11:25.
Denken Sie jetzt daran, dass atdstandardmäßig nicht die Fertigstellung der Jobs protokolliert wird. Weitere Informationen finden Sie unter diesem Link . Es ist besser, wenn Ihre Anwendung über eine eigene Protokollierung verfügt.
Sie können Jobs in planen. cronWeitere Informationen finden Sie unter: man cronAnzeigen der Optionen oder crontab -eHinzufügen neuer Jobs. /var/log/cronkann auf Informationen zur Ausführung von Jobs überprüft werden.
Zu sleep system call Ihrer Information: Die aktuelle Ausführung wird angehalten und für das übergebene Argument geplant.
BEARBEITEN:
Wie @Gaius bereits erwähnt hat, können Sie dem Befehl auch Minuten hinzufügen. Aber atsagen wir mal, die Zeit ist 12:30:30und jetzt haben Sie den Scheduler mit ausgeführt now +1 minutes. Obwohl 1 Minute angegeben wurde, was 60 Sekunden atentspricht, wartet das Programm nicht wirklich, bis 12:31:30der Job ausgeführt wird, sondern führt den Job unter aus 12:31:00. Die Zeiteinheiten können sein minutes, hours, days, or weeks. Weitere Informationen finden Sie unterman at
Dies ist nicht wahr, Sie können einen at-Job für beispielsweise jetzt +1 Minute einplanen, um in einer Minutenzeit zu laufen
Gaius,
29
Mit bashBuiltins können Sie Folgendes tun:
coproc read -t 10&& wait "$!"|| true
10 Sekunden schlafen ohne zu benutzen sleep. Das coprocist so zu machen, dass reads stdin eine Pfeife ist, aus der nie etwas rauskommt. Dies || trueliegt daran wait, dass der Beendigungsstatus eine SIGALRM-Übermittlung widerspiegelt, die dazu führen würde, dass die Shell beendet wird, wenn die errexitOption festgelegt ist.
In anderen Schalen:
mkshund eingebaut ksh93haben sleep, keinen Sinn, etwas anderes zu verwenden (obwohl sie beide auch unterstützen read -t).
zshunterstützt auch read -t, hat aber auch einen eingebauten Wrapper select(), so dass Sie auch verwenden können:
@ JeffSchaller Ich würde es vermeiden, da das eine belegte Schleife ist.
Stéphane Chazelas
@ StéphaneChazelas Ich würde nicht erwarten, dass es sich um eine Busy-Loop handelt. Ich würde erwarten, dass alle Shells readmit select (2) oder ähnlichem implementiert werden (dies impliziert, dass Read-with-Timeout eine gute Antwort auf diese Frage wäre). Ich drücke eher Überraschung als Widerspruch zu Ihnen aus, aber können Sie auf eine weitere Diskussion darüber hinweisen?
Norman Gray
5
@NormanGray /dev/zeroist eine Datei, die unendlich viele Daten (NUL-Bytes) enthält. So readwird so viel wie möglich in diesen 10 Sekunden gelesen. Zum Glück wird in dem Fall, in dem bashdas Speichern von NUL-Bytes in seinen Variablen nicht unterstützt wird, kein Speicher verbraucht, aber die CPU-Ressourcen werden trotzdem beansprucht.
Stéphane Chazelas
1
Wenn @NormanGray von einem Terminal aus ausgeführt wird, handelt /dev/stdoutes sich um das tty-Gerät. Dies hätte also Nebenwirkungen (wie das Stoppen des Skripts, wenn es im Hintergrund ausgeführt wird) und würde zurückgegeben, wenn der Benutzer beispielsweise die Eingabetaste drückt. read -t 10 /dev/stdout | :würde unter Linux funktionieren, aber nur unter Linux, während coprocunabhängig vom Betriebssystem funktionieren sollte.
Stéphane Chazelas
7
Einige andere Ideen.
top -d10 -n2 >/dev/null
vmstat 102>/dev/null
sar 101>/dev/null
timeout 10s tail -f /dev/null
Du hast meine Vorstellung von Zeitlimit / Timeout "gestohlen" ... +1
Rui F Ribeiro
1
Ohhhh mein Gott, danke, ich war in einer Situation ohne Schlaf, top ist der Wahnsinn!
Fire-Dragon-DoL
6
Da es Antworten gibt, die vorschlagen, die nicht standardmäßige -t delayOption von zu verwenden read, haben Sie hier die Möglichkeit, in einer Standard-Shell ein Zeitlimit für das Lesen festzulegen:
{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss";}
Das wäre in der Tat Pause für eine Dauer im Bereich irgendwo zwischen 9 und 10 Sekunden aber (aufgrund eines Fehlers inbash , zshund mkshhatte ähnliche Probleme , aber seit behoben)
Stéphane Chazelas
7
Ein guter Weg, um Wärme zu machen.
Strg-Alt-Delor
6
Ich werde nicht das erste Mal beschuldigt, voller heißer Luft zu sein! :)
Dies ist nicht der Fall, wenn der Prozess interaktionsfrei oder im Hintergrund ausgeführt werden muss, oder?
ss_iwe
Richtig: Aber das war nicht die Anforderung des OP gemäß der ursprünglichen Frage, also immer noch eine gültige Antwort ... ;
Fabby,
1
OP gibt speziell ein Beispiel (mit sleep) und fragt nach einer gleichwertigen Alternative ohne. Also readnicht analysieren, sorry. ;)
AnoE
@AnoE Stéphanes Antwort ist natürlich die beste, meine ist nur die älteste --- press «enter» to continue --- ;-)
Fabby
4
In den Tagen von Mikrocomputern, auf denen BASIC ausgeführt wurde, wurden Verzögerungen normalerweise mit einer leeren Schleife ausgeführt:
FOR I = 1 TO 10000:NEXT
Das gleiche Prinzip könnte verwendet werden, um eine Verzögerung in ein Shell-Skript einzufügen:
COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done
Das Problem bei diesem Ansatz ist natürlich, dass die Länge der Verzögerung von Maschine zu Maschine entsprechend ihrer Prozessorgeschwindigkeit (oder sogar auf derselben Maschine unter verschiedenen Lasten) variiert. Im Gegensatz dazu sleepwird es wahrscheinlich auch Ihre CPU (oder einen seiner Kerne) ausschöpfen.
Verzögerungsschleifen sind eine schreckliche Idee für alles andere als den kürzesten Ruhezustand (ein paar Nanosekunden oder Taktzyklen in einem Gerätetreiber) auf jeder modernen CPU, auf der ein Unix-ähnliches Betriebssystem ausgeführt werden kann. Das heißt, ein so kurzer Ruhezustand, dass die CPU während des Wartens keine weiteren Aktionen ausführen kann, z. B. einen anderen Prozess einplanen oder in einen Energiesparmodus wechseln kann, bevor sie bei einem Timer-Interrupt aufwacht. Die dynamische CPU-Frequenz macht es unmöglich, eine Verzögerungsschleife für Zählimpulse pro Sekunde zu kalibrieren, außer als Mindestverzögerung, die bei niedrigen Taktraten möglicherweise viel länger schläft, bevor sie hochgefahren wird.
Peter Cordes
Alte Computer hatten einen Stromverbrauch, der viel weniger von der Arbeitslast abhängig war. Moderne CPUs müssen verschiedene Teile des Chips so weit wie möglich dynamisch ausschalten, um nicht zu schmelzen (z. B. Teile der FPU- oder SIMD-Ausführungseinheiten ausschalten, während nur ganzzahliger Code ausgeführt wird, oder zumindest das Taktsignal auf Teile des Chips leiten das muss kein Wechsel sein). Der Energiesparmodus im Leerlauf (anstatt in einer Endlosschleife auf Timer-Interrupts zu warten) ist ebenfalls aktueller als die von Ihnen erwähnten alten Computer.
Es tut mir leid, dass Sie Ihre Bearbeitung auf das F zurückgesetzt haben: Sie haben den Hauptzweck der OPs-Frage geändert, wodurch die einfachste Antwort von allen ungültig würde ... ¯ \ _ (ツ) _ / ¯
Fabby
3
Ein Klassiker aus dem Land der Fenster und Batches:
ping -c 11 localhost >/dev/null && echo "This is a test"
Eine falsche Konfiguration der Firewall oder des Namenssystems kann zu einer erheblichen zusätzlichen Verzögerung führen.
Spektren
1
127.0.0.1 ... @spectras
AnoE
1
Zum Glück wird es nicht mehr benötigt, da Windows jetzt den systemeigenen Energiesparmodus unterstützt.
Baldrickk
1
@AnoE> löst den Namenssystemteil, nicht den Firewallteil. Obwohl dies nicht üblich ist, kann es so konfiguriert werden, dass Pings im Hintergrund auf der lokalen Schnittstelle gelöscht werden. Das führt dazu, dass Ping viel länger wartet.
Spektren
+1 für die "schönen" Erinnerungen
AC
0
Wenn Sie interaktiv auf eine neue Zeile in einer Datei warten möchten, dann
tail -f
.
Warten auf eine Änderung in einem Dateisystem? Dann benutze zB
inotify / inoticoming
.
Und es gibt andere Möglichkeiten, je nachdem, was Sie mit "warten" meinen.
sleep
?at
könnte eines sein, aber ich konnte keine Verwendungsbeispiele finden.Antworten:
Sie haben Alternativen zu
sleep
: Sie sindat
undcron
. Im Gegensatz dazusleep
müssen Sie den Zeitpunkt angeben, zu dem sie ausgeführt werden sollen.Stellen Sie sicher, dass der
atd
Dienst ausgeführt wird, indem Sie ausführenservice atd status
.Angenommen, das Datum ist 11:17 Uhr UTC. Wenn Sie einen Befehl , um 11:25 UTC ausführen müssen, ist die Syntax:
echo "This is a test" | at 11:25
.Denken Sie jetzt daran, dass
atd
standardmäßig nicht die Fertigstellung der Jobs protokolliert wird. Weitere Informationen finden Sie unter diesem Link . Es ist besser, wenn Ihre Anwendung über eine eigene Protokollierung verfügt.Sie können Jobs in planen.
cron
Weitere Informationen finden Sie unter:man cron
Anzeigen der Optionen odercrontab -e
Hinzufügen neuer Jobs./var/log/cron
kann auf Informationen zur Ausführung von Jobs überprüft werden.Zu
sleep system call
Ihrer Information: Die aktuelle Ausführung wird angehalten und für das übergebene Argument geplant.BEARBEITEN:
Wie @Gaius bereits erwähnt hat, können Sie dem Befehl auch Minuten hinzufügen. Aber
at
sagen wir mal, die Zeit ist12:30:30
und jetzt haben Sie den Scheduler mit ausgeführtnow +1 minutes
. Obwohl 1 Minute angegeben wurde, was 60 Sekundenat
entspricht, wartet das Programm nicht wirklich, bis12:31:30
der Job ausgeführt wird, sondern führt den Job unter aus12:31:00
. Die Zeiteinheiten können seinminutes, hours, days, or weeks
. Weitere Informationen finden Sie unterman at
z.B:
echo "ls" | at now +1 minutes
quelle
Mit
bash
Builtins können Sie Folgendes tun:10 Sekunden schlafen ohne zu benutzen
sleep
. Dascoproc
ist so zu machen, dassread
s stdin eine Pfeife ist, aus der nie etwas rauskommt. Dies|| true
liegt daranwait
, dass der Beendigungsstatus eine SIGALRM-Übermittlung widerspiegelt, die dazu führen würde, dass die Shell beendet wird, wenn dieerrexit
Option festgelegt ist.In anderen Schalen:
mksh
und eingebautksh93
habensleep
, keinen Sinn, etwas anderes zu verwenden (obwohl sie beide auch unterstützenread -t
).zsh
unterstützt auchread -t
, hat aber auch einen eingebauten Wrapperselect()
, so dass Sie auch verwenden können:Wenn Sie die Ausführung von einer interaktiven Shell-Sitzung aus planen möchten, lesen Sie auch das
zsh/sched
Modul inzsh
.quelle
read -t 10 < /dev/zero || true
?read
mit select (2) oder ähnlichem implementiert werden (dies impliziert, dass Read-with-Timeout eine gute Antwort auf diese Frage wäre). Ich drücke eher Überraschung als Widerspruch zu Ihnen aus, aber können Sie auf eine weitere Diskussion darüber hinweisen?/dev/zero
ist eine Datei, die unendlich viele Daten (NUL-Bytes) enthält. Soread
wird so viel wie möglich in diesen 10 Sekunden gelesen. Zum Glück wird in dem Fall, in dembash
das Speichern von NUL-Bytes in seinen Variablen nicht unterstützt wird, kein Speicher verbraucht, aber die CPU-Ressourcen werden trotzdem beansprucht./dev/stdout
es sich um das tty-Gerät. Dies hätte also Nebenwirkungen (wie das Stoppen des Skripts, wenn es im Hintergrund ausgeführt wird) und würde zurückgegeben, wenn der Benutzer beispielsweise die Eingabetaste drückt.read -t 10 /dev/stdout | :
würde unter Linux funktionieren, aber nur unter Linux, währendcoproc
unabhängig vom Betriebssystem funktionieren sollte.Einige andere Ideen.
quelle
Da es Antworten gibt, die vorschlagen, die nicht standardmäßige
-t delay
Option von zu verwendenread
, haben Sie hier die Möglichkeit, in einer Standard-Shell ein Zeitlimit für das Lesen festzulegen:Das Argument für
stty time
ist in Zehntelsekunden.quelle
Verwenden der integrierten Variablen bash
$SECONDS
und einer Besetzt-Schleife:quelle
bash
,zsh
undmksh
hatte ähnliche Probleme , aber seit behoben)Der älteste Trick im Buch:
Einfach drücken Enterund es geht weiter!
quelle
sleep
) und fragt nach einer gleichwertigen Alternative ohne. Alsoread
nicht analysieren, sorry. ;)--- press «enter» to continue ---
;-)In den Tagen von Mikrocomputern, auf denen BASIC ausgeführt wurde, wurden Verzögerungen normalerweise mit einer leeren Schleife ausgeführt:
FOR I = 1 TO 10000:NEXT
Das gleiche Prinzip könnte verwendet werden, um eine Verzögerung in ein Shell-Skript einzufügen:
COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done
Das Problem bei diesem Ansatz ist natürlich, dass die Länge der Verzögerung von Maschine zu Maschine entsprechend ihrer Prozessorgeschwindigkeit (oder sogar auf derselben Maschine unter verschiedenen Lasten) variiert. Im Gegensatz dazu
sleep
wird es wahrscheinlich auch Ihre CPU (oder einen seiner Kerne) ausschöpfen.quelle
Es gibt kein eingebautes Gerät, das dasselbe macht wie
sleep
(essleep
sei denn, es ist eingebaut). Es gibt jedoch einige andere Befehle, die warten.Einige davon sind.
at
undcron
: Dient zum Planen von Aufgaben zu einem bestimmten Zeitpunkt.inotifywait
: Dient zum Warten auf eine Datei oder zum Ändern / Entfernen / Hinzufügen / etcquelle
at
angeben?cron
Aufgaben speichern incrontab
, oder? Wo werdenat
die geplanten Daten gespeichert?Ein Klassiker aus dem Land der Fenster und Batches:
quelle
Wenn Sie interaktiv auf eine neue Zeile in einer Datei warten möchten, dann
.Warten auf eine Änderung in einem Dateisystem? Dann benutze zB
.Und es gibt andere Möglichkeiten, je nachdem, was Sie mit "warten" meinen.
quelle