Ich benutze startx
, um X zu starten, das meine auswertet .xinitrc
. In meinem starte .xinitrc
ich meinen Fenstermanager mit /usr/bin/mywm
. Wenn ich jetzt meine WM töte (um beispielsweise eine andere WM zu testen), wird X ebenfalls beendet, da das .xinitrc
Skript EOF erreicht hat. Also habe ich dies am Ende meiner .xinitrc
:
while true; do sleep 10000; done
Auf diese Weise wird X nicht beendet, wenn ich meine WM töte. Nun meine Frage: Wie kann ich einen unendlichen Schlaf machen, anstatt den Schlaf zu schleifen? Gibt es einen Befehl, mit dem das Skript eingefroren werden kann?
Freundliche Grüße
sleep infinity
, obwohl es eine coole Sache war, etwas über Linux zu lernen. Solltewhile true; do sleep 86400; done
jedoch ein adäquater Ersatz sein.infinity
wird in C von "string" in a konvertiertdouble
. Danndouble
wird das auf die maximal zulässigen Werte gekürzttimespec
, was eine sehr große Anzahl von Sekunden (architekturabhängig) bedeutet, aber theoretisch endlich.tail
blockiert nichtWie immer: Für alles gibt es eine Antwort, die kurz, leicht verständlich, leicht zu befolgen und völlig falsch ist. Hier
tail -f /dev/null
fällt in diese Kategorie;)Wenn Sie es mit betrachten, werden
strace tail -f /dev/null
Sie feststellen, dass diese Lösung weit davon entfernt ist, zu blockieren! Es ist wahrscheinlich noch schlimmer als diesleep
Lösung in der Frage, da es (unter Linux) wertvolle Ressourcen wie dasinotify
System verwendet. Auch andere Prozesse, die schreiben,/dev/null
umtail
Schleife zu machen . (Auf meinem Ubuntu64 16.10 werden auf einem bereits ausgelasteten System mehrere 10 Syscalls pro Sekunde hinzugefügt.)Die Frage war nach einem Blockierungsbefehl
Leider gibt es so etwas nicht ..
Lesen Sie: Ich kenne keine Möglichkeit, dies direkt mit der Shell zu archivieren.
Alles (gerade
sleep infinity
) kann durch ein Signal unterbrochen werden. Wenn Sie also wirklich sicher sein möchten, dass es nicht ausnahmsweise zurückkehrt, muss es in einer Schleife ausgeführt werden, wie Sie es bereits für Ihre getan habensleep
. Bitte beachten Sie, dass (unter Linux)/bin/sleep
anscheinend auf 24 Tage begrenzt ist (siehestrace sleep infinity
). Daher ist das Beste, was Sie wahrscheinlich tun können, Folgendes:(Beachten Sie, dass ich glaube, dass
sleep
Schleifen intern für höhere Werte als 24 Tage ausgeführt werden. Dies bedeutet jedoch: Sie blockieren nicht, sie werden sehr langsam wiederholt. Warum also nicht diese Schleife nach außen verschieben?).. aber Sie können mit einem unbenannten ganz nah kommen
fifo
Sie können etwas erstellen, das wirklich blockiert, solange keine Signale an den Prozess gesendet werden. Folgende Verwendungen
bash 4
, 2 PIDs und 1fifo
:Sie können überprüfen, ob dies wirklich blockiert,
strace
wenn Sie möchten:Wie das aufgebaut war
read
blockiert, wenn keine Eingabedaten vorhanden sind (siehe einige andere Antworten). Dastty
(aka.stdin
) Ist jedoch normalerweise keine gute Quelle, da es geschlossen wird, wenn sich der Benutzer abmeldet. Es könnte auch einige Eingaben von der stehlentty
. Nicht nett.Um zu
read
blockieren, müssen wir auf so etwas wie ein warten,fifo
das niemals etwas zurückgibt. Darinbash 4
befindet sich ein Befehl, der uns genau Folgendes liefern kannfifo
:coproc
. Wenn wir auch auf die Blockierung wartenread
(was unsere istcoproc
), sind wir fertig. Leider muss dies zwei PIDs und eine offen haltenfifo
.Variante mit einem Namen
fifo
Wenn Sie sich nicht die Mühe machen, einen Namen zu verwenden
fifo
, können Sie dies wie folgt tun:Das Nicht-Verwenden einer Schleife beim Lesen ist etwas schlampig, aber Sie können dies
fifo
so oft wiederverwenden, wie Sie möchten, und dieread
s-Terminierung verwendentouch "$HOME/.pause.fifo"
(wenn mehr als ein einziger Lesevorgang wartet, werden alle auf einmal beendet).Oder verwenden Sie den Linux-
pause()
SystemaufrufFür die unendliche Blockierung gibt es einen Linux-Kernel-Aufruf namens
pause()
, der das tut, was wir wollen: Warten Sie für immer (bis ein Signal eintrifft). Es gibt jedoch (noch) kein Userspace-Programm dafür.C.
Ein solches Programm zu erstellen ist einfach. Hier ist ein Ausschnitt ein sehr kleines Linux - Programm aufgerufen zu erstellen ,
pause
die auf unbestimmte Zeit pausiert (Bedürfnissediet
,gcc
etc.):python
Wenn Sie etwas nicht selbst kompilieren möchten, aber
python
installiert haben, können Sie dies unter Linux verwenden:(Hinweis:
exec python -c ...
Zum Ersetzen der aktuellen Shell wird eine PID freigegeben. Die Lösung kann auch durch eine E / A-Umleitung verbessert werden, wodurch nicht verwendete FDs freigegeben werden. Dies liegt bei Ihnen.)So funktioniert das (glaube ich):
ctypes.CDLL(None)
Lädt die Standard-C-Bibliothek und führt die darin enthaltenepause()
Funktion in einer zusätzlichen Schleife aus. Weniger effizient als die C-Version, funktioniert aber.Meine Empfehlung für Sie:
Bleib im Schlaf. Es ist leicht zu verstehen, sehr portabel und blockiert die meiste Zeit.
quelle
trap
(der das Verhalten der Shell in Signale umwandelt) noch den Hintergrund (der es der Shell ermöglicht, Signale vom Terminal abzufangen, wie Strg + C). Alsosleep infinity
ist genug (verhält sich wieexec sleep infinity
wenn es die letzte Aussage ist. Um den Unterschied zu sehenstrace -ffDI4 bash -c 'YOURCODEHERE'
). Der Schleifenschlaf ist besser, da ersleep
unter bestimmten Umständen zurückkehren kann. Zum Beispiel möchten Sie nicht, dass X11 auf einem plötzlich heruntergefahren wirdkillall sleep
, nur weil es anstelle einer Schlafschleife.xstartup
endetsleep infinity
.s6-pause
ein Userland-Befehl zum Ausführenpause()
, der optional verschiedene Signale ignoriert./bin/sleep
ist nicht auf 24 Tage begrenzt, wie Sie sagen. Es wäre schön, wenn Sie das aktualisieren könnten. Unter Linux ist dieser Code derzeit aktiv. Es begrenzt einzelnenanosleep()
Systemaufrufe auf 24 Tage, ruft sie jedoch in einer Schleife auf. Sollte alsosleep infinity
nicht nach 24 Tagen beendet werden. Diedouble
positive Unendlichkeit wird in a umgewandeltstruct timespec
. Betrachtet manrpl_nanosleep
in GDB,infinity
wird{ tv_sec = 9223372036854775807, tv_nsec = 999999999 }
auf Ubuntu 16.04 konvertiert .strace
ich allein nicht beweisen kann, dass wirklich ein Schleifencode kompiliert istsleep
, und ich nicht 24 Tage warten möchte, nur um dies zu testen (oder zu dekompilieren/bin/sleep
). Es ist immer besser, defensiv zu programmieren, wenn es keinen harten mathematischen Beweis gibt, dass etwas wirklich so ist, wie es scheint. Vertraue auch nie etwas:killall -9 sleep
Vielleicht scheint das hässlich, aber warum nicht einfach rennen
cat
und es für immer auf Eingaben warten lassen?quelle
cat
es?mkfifo pipe && cat pipe
TL; DR:
sleep infinity
schläft tatsächlich die maximal zulässige Zeit, die endlich ist.Als ich mich fragte, warum dies nirgendwo dokumentiert ist, machte ich mir die Mühe, die Quellen von GNU-Coreutils zu lesen, und stellte fest, dass es ungefähr Folgendes ausführt:
strtod
C stdlib für das erste Argument, um 'unendlich' in die doppelte Genauigkeit umzuwandeln. Unter der Annahme einer doppelten Genauigkeit von IEEE 754 wird der positive 64-Bit- Unendlichkeitswert in derseconds
Variablen gespeichert .xnanosleep(seconds)
( gefunden in gnulib ), dies ruft wiederumdtotimespec(seconds)
( auch in gnulib ) auf, um vondouble
zu konvertierenstruct timespec
.struct timespec
ist nur ein Zahlenpaar: ganzzahliger Teil (in Sekunden) und gebrochener Teil (in Nanosekunden). Die naive Umwandlung der positiven Unendlichkeit in eine Ganzzahl würde zu einem undefinierten Verhalten führen (siehe §6.3.1.4 aus dem C-Standard), daher wird es stattdessen auf abgeschnittenTYPE_MAXIMUM (time_t)
.TYPE_MAXIMUM (time_t)
ist nicht im Standard festgelegt (auchsizeof(time_t)
nicht). Lassen Sie uns zum Beispiel x86-64 aus einem aktuellen Linux-Kernel auswählen.Dies ist
TIME_T_MAX
im Linux-Kernel, der wie folgt definiert isttime.h
:Beachten Sie, dass
time_t
ist__kernel_time_t
undtime_t
istlong
; Das LP64-Datenmodell wird verwendet, alsosizeof(long)
8 (64 Bit).Was zu :
TIME_T_MAX = 9223372036854775807
.Das heißt:
sleep infinite
ergibt eine tatsächliche Schlafzeit von 9223372036854775807 Sekunden (10 ^ 11 Jahre). Und für 32-Bit-Linux-Systeme (sizeof(long)
4 (32 Bit)): 2147483647 Sekunden (68 Jahre; siehe auch Problem Jahr 2038 ).Bearbeiten : Anscheinend ist die
nanoseconds
aufgerufene Funktion nicht direkt der Syscall, sondern ein OS-abhängiger Wrapper (auch in gnulib definiert ).Es gibt einen zusätzlichen Schritt als Ergebnis: Bei einigen Systemen , wo
HAVE_BUG_BIG_NANOSLEEP
isttrue
der Schlaf wird abgeschnitten , bis 24 Tage und dann in einer Schleife aufgerufen. Dies ist bei einigen (oder allen?) Linux-Distributionen der Fall. Beachten Sie, dass dieser Wrapper möglicherweise nicht verwendet wird, wenn ein Test zur Konfigurationszeit erfolgreich ist ( Quelle ).Dies wäre insbesondere
24 * 24 * 60 * 60 = 2073600 seconds
(plus 999999999 Nanosekunden); Dies wird jedoch in einer Schleife aufgerufen, um die angegebene Gesamtschlafzeit zu berücksichtigen. Daher bleiben die bisherigen Schlussfolgerungen gültig.Zusammenfassend ist die resultierende Schlafzeit nicht unendlich, sondern für alle praktischen Zwecke hoch genug , selbst wenn der resultierende tatsächliche Zeitraffer nicht tragbar ist; Das hängt vom Betriebssystem und der Architektur ab.
Um die ursprüngliche Frage zu beantworten, ist dies natürlich gut genug, aber wenn Sie aus irgendeinem Grund (einem sehr ressourcenbeschränkten System) wirklich einen nutzlosen zusätzlichen Countdown-Timer vermeiden möchten, ist es wahrscheinlich die richtigste Alternative, die
cat
in anderen Antworten beschriebene Methode zu verwenden .quelle
sleep infinity
wird nun tatsächlich für immer ohne Schleifen schlafen: lists.gnu.org/archive/html/bug-gnulib/2020-02/msg00081.htmlsleep infinity
sieht am elegantesten aus, aber manchmal funktioniert es aus irgendeinem Grund nicht. In diesem Fall können Sie andere Sperrbefehle versuchen wiecat
,read
,tail -f /dev/null
,grep a
usw.quelle
tail -f /dev/null
war auch eine funktionierende Lösung für mich auf einer SaaS-Plattformtail -f /dev/null
hat auch den vorteil, stdin nicht zu konsumieren. Ich habe es aus diesem Grund benutzt.Was ist mit dem Senden eines SIGSTOP an sich selbst?
Dies sollte den Vorgang anhalten, bis SIGCONT empfangen wird. Welches ist in Ihrem Fall: nie.
quelle
Lassen Sie mich erklären, warum dies
sleep infinity
funktioniert, obwohl es nicht dokumentiert ist. jp48s antwort ist ebenfalls nützlich.Das Wichtigste: Durch Angabe von
inf
oderinfinity
(beide ohne Berücksichtigung der Groß- und Kleinschreibung) können Sie so lange schlafen, wie es Ihre Implementierung zulässt (dh den kleineren Wert vonHUGE_VAL
undTYPE_MAXIMUM(time_t)
).Lassen Sie uns nun die Details untersuchen. Der Quellbefehlscode
sleep
kann aus coreutils / src / sleep.c gelesen werden . Im Wesentlichen macht die Funktion dies:Verstehen
xstrtod (argv[i], &p, &s, cl_strtod)
xstrtod()
Laut gnulib / lib / xstrtod.c
xstrtod()
konvertiert der Aufruf von stringargv[i]
in einen Gleitkommawert und speichert ihn*s
mithilfe einer Konvertierungsfunktion incl_strtod()
.cl_strtod()
Wie aus coreutils / lib / cl-strtod.c ersichtlich ,
cl_strtod()
wird eine Zeichenfolge mithilfe von in einen Gleitkommawert konvertiertstrtod()
.strtod()
Entsprechend
man 3 strtod
,strtod()
wandelt eine Zeichenkette auf einen Wert von Typdouble
. Die Manpage sagtund eine Unendlichkeit ist definiert als
Obwohl das Dokument erzählt
Es ist nicht klar, wie eine Unendlichkeit behandelt wird. Sehen wir uns also den Quellcode gnulib / lib / strtod.c an . Was wir lesen wollen, ist
Somit werden
INF
undINFINITY
(beide ohne Berücksichtigung der Groß- und Kleinschreibung) als betrachtetHUGE_VAL
.HUGE_VAL
FamilieVerwenden wir N1570 als C-Standard.
HUGE_VAL
,HUGE_VALF
UndHUGE_VALL
sind Makros definiert in §7.12-3und in §7.12.1-5
Verstehen
xnanosleep (s)
Jetzt verstehen wir alles Wesentliche von
xstrtod()
. Aus den obigen Erklärungen ist kristallklar, dassxnanosleep(s)
wir zuerst gesehen haben, was tatsächlich bedeutetxnanosleep(HUGE_VALL)
.xnanosleep()
Nach dem Quellcode gnulib / lib / xnanosleep.c ,
xnanosleep(s)
tut im Wesentlichen diese:dtotimespec()
Diese Funktion konvertiert ein Argument vom Typ
double
in ein Objekt vom Typstruct timespec
. Da es sehr einfach ist, möchte ich den Quellcode gnulib / lib / dtotimespec.c zitieren . Alle Kommentare wurden von mir hinzugefügt.Da
time_t
es sich um einen integralen Typ handelt (siehe §7.27.1-3), nehmen wir natürlich an, dass der Maximalwert des Typstime_t
kleiner alsHUGE_VAL
(des Typsdouble
) ist, was bedeutet, dass wir in den Überlauffall eintreten. (Diese Annahme ist eigentlich nicht erforderlich, da das Verfahren in allen Fällen im Wesentlichen dasselbe ist.)make_timespec()
Die letzte Wand, die wir erklimmen müssen, ist
make_timespec()
. Zum Glück ist es so einfach, dass das Zitieren des Quellcodes gnulib / lib / timespec.h ausreicht.quelle
Ich hatte vor kurzem die Notwendigkeit, dies zu tun. Ich habe die folgende Funktion entwickelt, mit der bash für immer schlafen kann, ohne ein externes Programm aufzurufen:
ANMERKUNG: Ich habe zuvor eine Version davon veröffentlicht, die den Dateideskriptor jedes Mal öffnet und schließt, aber ich habe festgestellt, dass auf einigen Systemen, die dies hunderte Male pro Sekunde tun, irgendwann blockiert wird. Somit behält die neue Lösung den Dateideskriptor zwischen den Aufrufen der Funktion bei. Bash wird es sowieso beim Verlassen aufräumen.
Dies kann genau wie / bin / sleep aufgerufen werden und wird für die angeforderte Zeit schlafen. Ohne Parameter aufgerufen, bleibt es für immer hängen.
Es gibt eine Beschreibung mit übermäßigen Details in meinem Blog hier
quelle
Dieser Ansatz verbraucht keine Ressourcen, um den Prozess am Leben zu erhalten.
while :; do sleep 1; done & kill -STOP $! && wait $!
Nervenzusammenbruch
while :; do sleep 1; done &
Erstellt einen Dummy-Prozess im Hintergrundkill -STOP $!
Stoppt den Hintergrundprozesswait $!
Warten Sie auf den Hintergrundprozess, dieser wird für immer blockiert, da der Hintergrundprozess zuvor gestoppt wurdequelle
Versuchen Sie, den neuen Manager mit
--replace
oder,-replace
falls verfügbar , auszuführen, anstatt den Fenstermanager zu beenden .quelle
--replace
bekomme ich immer eine Warnung wieanother window manager is already running
. Das macht für mich aber nicht viel Sinn.Kein Warten auf den Schlafprozess des Kindes.
quelle
stdin
wenn dies noch mit dem verbunden isttty
. Wenn Sie es mit< /dev/null
Busy-Loops ausführen . Es kann in bestimmten Situationen von Nutzen sein, daher stimme ich nicht ab.