Ich verwende Ubuntu Server 16.04 und at
möchte das Dienstprogramm in meiner aktuellen Sitzung verwenden, um in einer Minute etwas zu tun (sagen wir eine echo
), ohne ein bestimmtes Datum und eine bestimmte Uhrzeit anzugeben - nur eine Minute vor der aktuellen Uhrzeit.
Dies ist fehlgeschlagen:
echo 'hi' | at 1m
Der Grund , warum ich wähle at
über sleep
, weil Schlaf Handicaps aktuelle Sitzung und ist in einer anderen Sitzung, anstatt die, die wir Arbeit mit den meisten Zeit zu Verzögerungsbefehlen dafür besser geeignet. AFAIR at
verhält sich nicht so und behindert meine Sitzung nicht.
Update_1
Nach der Antwort von Pied Piper habe ich versucht:
(sleep 1m; echo 'hi') &
Ich habe ein Problem mit dieser Methode: Der Stream "hi" wird in meiner primären Eingabeaufforderung gedruckt und fügt außerdem eine leere sekundäre Eingabeaufforderung ( _
) direkt unter der primären Eingabeaufforderung hinzu, die ihn enthält. Siehe:
USER@:~# (sleep 1m; echo 'hi') &
[1] 22731
USER@:~# hi
^C
[1]+ Done
Update_2
Nach der Antwort von Peter Corde habe ich versucht:
(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
Dies funktioniert anscheinend in Bash 4.4 einwandfrei, in einigen älteren Versionen jedoch nicht (siehe Kommentare in der Antwort). Ich persönlich benutze Bash 4.3 in meinen eigenen Umgebungen.
Antworten:
Nein, es ist nicht "gedruckt in Ihrem
stdin
".Wenn Sie die Eingabetaste drücken, wird nicht versucht, den
hi
Befehl auszuführen . Es ist nur so, dass der Hintergrundecho
gedruckt wurde,hi
während sich der Cursor hinter Ihrer Eingabeaufforderung befand.Vielleicht möchten Sie eine führende Zeile drucken , wie z
(sleep 1m && echo -e '\nhi' &)
. (Passen Sie nach Bedarf dieecho
in Ihrer Shell an. Oder verwenden Sie sieprintf
für die Portabilität.)Ich habe die
&
Innenseite der Unterschale so eingestellt, dass der Hintergrundjob "verleugnet" wird, damit Sie auch das "Rauschen" von vermeiden[1]+ Done
. Wird&&
zwischen den Befehlen&
für die gesamte zusammengesetzte Befehlskette angewendet, sodass sofort zur Shell-Eingabeaufforderung zurückgekehrt wird, anstatt aufsleep
das Beenden zu warten , wie Sie es gewohnt sind(sleep 1; echo ... &)
Folgendes passiert (mit einer Verzögerung von 1 Sekunde):
Bash weiß nicht, dass
echo
etwas gedruckt wurde, daher muss die Eingabeaufforderung nicht erneut gedruckt oder der Bildschirm aufgeräumt werden. Sie können das manuell mit tuncontrol-L
.Sie können eine Shell-Funktion schreiben, die bash abruft, um die Eingabeaufforderung nach
echo
Beendigung erneut zu drucken . Wenn Sie dies tun,echo "$PS1"
werden keine bereits eingegebenen Zeichen reproduziert.kill -WINCH $$
Auf meinem System wird Bash angewiesen, die Eingabeaufforderungszeile erneut zu drucken, ohne den Bildschirm zuhi
löschen. Vor der Eingabeaufforderung wird eine eigene Zeile angezeigt. SIGWINCH wird automatisch gesendet, wenn sich die Größe von WINdow ändert, und die Antwort von bash darauf geschieht, was wir wollen.Es könnte mit anderen Shells funktionieren, aber ich versuche nicht, diese zu 100% portabel / POSIX zu machen. ( Leider funktioniert dies nur mit bash4.4, nicht mit bash4.3, oder hängt von einer Einstellung ab, die mir nicht bekannt ist. )
Sie können dies leicht in eine Shell-Funktion einschließen, die ein Schlafargument und eine Nachricht entgegennimmt.
bash 4.3 druckt seine Eingabeaufforderung nach SIGWINCH nicht erneut, daher funktioniert dies dort nicht. Ich habe
shopt -s checkwinsize
auf beiden Systemen aktiviert, aber es funktioniert nur auf dem Bash 4.4-System (Arch Linux).Wenn es nicht funktioniert, können Sie versuchen
(sleep 2 && echo -e '\nhi' && echo "$PS1" &)
, was "funktioniert", wenn die Befehlszeile leer ist. (Es ignoriert auch die Möglichkeit, die festgelegtPROMPT_COMMAND
ist.)Es gibt keine wirklich saubere Möglichkeit, die Terminalausgabe mit dem zu mischen, was Sie später auf Ihrem Terminal tun, wenn der Timer ausgelöst wird. Wenn Sie gerade einen Bildlauf durchführen
less
, können Sie ihn leicht übersehen.Wenn Sie nach etwas mit interaktiven Ergebnissen suchen, empfehle ich Ihnen, eine Audiodatei abzuspielen. zB mit einem Kommandozeilen-Player wie
mpv
(nette Abzweigung von MPlayer2). Oder wählen Sie eine Videodatei aus, um ein neues Fenster zu öffnen.Vielleicht möchten Sie
echo
ein neues xterm / konsole / gnome-terminal öffnen. Verwenden Sie eine Option, mit der das Terminal nach dem Beenden des Befehls geöffnet bleibt.quelle
Enter
Tastendruckereignis zu emulieren , direkt nachdem das Echo angezeigt wurde, sodass ich automatisch zur primären Eingabeaufforderung der Konsole zurückkehren würde ?(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
.kill -WINCH $$
nicht aktualisieren , um die prompte der Schale in dem Endgerät ausgeführt wird . Das war der ganze Sinn, es zu benutzen. Wenn Sie die Eingabetaste drücken, wird ein teilweise eingegebener Befehl gesendet, WINCH jedoch nicht, wie ich gezeigt habe. Wenn Sie nichts eingegeben haben, wird eine leere Eingabeaufforderung angezeigt.rm -rf ~/some/directory
Eingabe begonnen hätten, würde die Eingabe möglicherweise zur falschen Zeit ausgeführtrm -rf ~/
. (Sicherheits - Tipp: Wegen Finish eingeben und dann steuern-a und Änderungls
zurm -rf
, so fett fingern jederzeit Geben Sie nicht den Tag verderben.)(sleep 2 && echo -e '\nhi' && kill -WINCH $$ &)
und nachdem das Echo erschienen ist, habe ich eine leere Eingabeaufforderung erhalten, erst nachdemEnter
ich auf die primäre Eingabeaufforderung zurückgekehrt bin ... Entschuldigung, wenn ich Sie falsch verstehe, bin ich ziemlich neu bei Bash.screen
Sitzung (und nur über SSH) auf einem älteren Ubuntu-System getestet , und ich habe das von Ihnen beschriebene Verhalten erhalten.Die korrekte Verwendung ist
at <timespec>
, wo<timespec>
ist die Zeitangabe. Sie können die-f
Option auch verwenden , um die Datei anzugeben, die die auszuführenden Befehle enthält. Wenn-f
und keine Umleitung verwendet wird, liest at die auszuführenden Befehle aus der Standardeingabe.Um in Ihrem Beispiel "some command" auszuführen (im folgenden Beispiel habe ich "some command" als "echo hi" ausgewählt), ist eine Minute nach dem Drücken von enter (now) die beabsichtigte
<timespec>
Verwendungnow + 1 minute
. Verwenden Sie den folgenden Befehl, um das gewünschte Ergebnis mit einer Ein-Linien-Lösung zu erzielen:echo 'echo hi' | at now + 1 minute
Dies soll (und wird) den
echo hi
Befehl nach einer Minute ausführen . Das Problem hierbei ist, dass derecho hi
Befehl vom Befehl at in einem Dummy-Tty ausgeführt wird und die Ausgabe an die Mailbox des Benutzers gesendet wird (sofern diese korrekt konfiguriert ist - was eine ausführlichere Erläuterung zum Konfigurieren einer Mailbox in erfordert eine Unix-Maschine und gehört nicht zum Umfang dieser Frage). Die Quintessenz ist, dass Sie das Ergebnis von nicht direktecho hi
in demselben Terminal sehen können, in dem Sie den Befehl ausgegeben haben. Die einfachste Alternative ist, Sie leiten es zu "irgendeiner Datei" um, zum Beispiel:echo 'echo hi > /tmp/at.out' | at now + 1 minute
Im obigen Beispiel ist "some file"
/tmp/at.out
und das erwartete Ergebnis ist, dass die Dateiat.out
unter / tmp nach einer Minute erstellt wird und den Text "hi" enthält.Zusätzlich zu dem
now + 1 minute
obigen Beispiel können viele andere Zeitangaben verwendet werden, auch einige komplexe. Der Befehl at ist intelligent genug, um für Menschen lesbare Befehle wie die folgenden zu interpretieren:now + 1 day
,13:25
,mid‐night
,noon
, ...Weitere Informationen zu den möglichen Zeitangaben finden Sie auf der Manpage von at, da die möglichen Abweichungen sehr umfangreich sind und Daten, relative oder absolute Zeiten usw. enthalten können.
quelle
at
Standardmäßig wird die Ausgabe per E-Mail gesendet, dies muss jedoch ordnungsgemäß konfiguriert sein, um zu funktionieren.at <timespec>
erfahren, was ist und welches Flag du benutzt hast und ob es zu Ubuntu 16.04 xenial passt.sleep
Führe das in einer Subshell aus:Hinweis: Unter Linux können Sie das Argument für den Ruhezustand in Sekunden oder mit dem Suffix s / m / h / d (für Sekunden, Minuten, Stunden, Tage) angeben. Bei BSD muss das Argument in Sekunden angegeben werden
quelle
stdin
) und nicht in meinerstdout
(wie bei einer regulärenecho
) ausgegeben .(sleep 10s; echo 'hi') & 1>
. Ich lese jetzt mehr dazu.stdin
und zu seinstdout
. Sie haben nichts damit zu tun, wo Dinge auf Ihrem Terminal erscheinen. Stattdessen sollten Sie sie in Bezug auf einen bestimmten Prozess (im Grunde genommen ein Programm) interpretieren . Die Standardeingabe ("stdin") für einen Prozess ist eine Quelle, von der der Prozess Daten lesen kann, und die Standardausgabe des Prozesses ("stdout") ist ein Ziel, in das Daten geschrieben werden können. Diese Quellen und Ziele können andere Programme oder Dateien oder das Terminal selbst sein (von Ihnen eingegebenes Material wird in stdin gespeichert und alles, was in stdout enthalten ist, wird angezeigt).Das ist fehlgeschlagen, weil Sie die Ausgabe von weiterleiten
echo "hi"
, was nurhi
dazu dientat
, aberat
erwartet, dass die Eingabe von der Standard-System-Shell ausgeführt werden kann (normalerweise bash, aber manchmal etwas anderes, je nach System).Dies:
wird erreichen, was Sie versuchen zu tun scheinen. Es wird ein Shell-Konstrukt namens "here document" verwendet, was im Allgemeinen die akzeptierte Methode ist, um diese Art von Dingen auszuführen (da es mehrere Zeilen besser verarbeitet als das Verwenden des
echo
Befehls und keine neue Datei erstellt werden muss, wie Sie es benötigen würden)cat
) und übersetzt in das etwas kompliziertere Äquivalent mitecho
:Es ist wahrscheinlich erwähnenswert, dass
at
eine Befehlsausgabe per E-Mail an den Benutzerat
gesendet wird, der den Befehl aufgerufen hat , anstatt die Ausgabe an das Terminal als einen Befehl zu senden, dessen Verwendungsleep
in einer Subshell verzögert wird . Dies bedeutet insbesondere, dass Sie die Ausgabe von Befehlen nur über ausführen können, wenn Sie das System angepasst haben oder beabsichtigen, Ihre lokale Mail-Spool zu lesenat
.quelle
syntax error. Last token seen: m Garbled time
. Ich habe keine Idee warum. Ich benutze Ubuntu 16.04, Bash 4.0. Vielleicht haben Sie das auf einem anderen System gemacht. Selbst wenn ich nurat
ohne weitere Argumente eingebe, erhalte ich immer noch den gleichen Fehler. Weitere Daten hier .at 1m
funktioniert nicht für eine posix-kompatibleat
. Der Befehl müsste seinat now + 1 minute
at
. Ich habe nur angenommen, dass Sie eine Version haben, die diese Syntax akzeptiert.at 1m
ist kein POSIX- System, aber es steht POSIX-kompatiblen Implementierungenat
frei, sie so zu interpretieren, wie sie möchten. Es macht eineat
Implementierung nicht weniger konform, wenn sie so interpretiert wird,now + 1 minute
als würde sie einen Fehler zurückgeben oder vor einem Monat bedeuten . IOW, es ist derat 1m
Code, der nicht POSIX ist.Kombinieren Sie die Antwort von @Peter Cordes und diese Antwort /programming/23125527/how-to-return-to-bash-prompt-after-printing-output-from-backgrounded-function/23125687#23125687
Der folgende Code stammt aus der letzten Antwort, mit einer kleinen Änderung von mir. Kompiliere es, um a.out abzulegen (welcher Name auch immer du willst)
Führen Sie dann den folgenden Befehl aus. (Ich stelle a.out in dir / tmp /, Sie müssen möglicherweise zu Ihrem wechseln.)
oder
BTW,
kill -WINCH $$
funktioniert gut für mich mit Bash 4.3 auf Gentoo.quelle
Aufbauend auf den obigen Antworten können Sie den eingebetteten Befehl so auf Ihr Terminal ausgeben lassen:
echo "echo hi >$(tty); kill -WINCH $$" | at now + 1 minute
Der
tty
Befehl gibt den Gerätepfad Ihres aktuellen Terminals zurück. Wenn Sie ihn in "$(...)
Bash" einschließen , wird er in einer Sub-Shell ausgeführt. Der Befehl "Kill" sendet ein Signal an den aktuellen Prozess, bei dem Bash die Aufforderung "$ PS1" erneut ausgibt.quelle