Frage Wiederhole einen Befehl jedes x Zeitintervall im Terminal?


Wie kann ich wiederholen ein Befehl in jedem Zeitintervall, damit ich Befehle ausführen kann Überprüfung  oder Überwachung  Verzeichnisse?

Es gibt keine Notwendigkeit für ein Skript, ich brauche nur einen einfachen Befehl im Terminal ausgeführt werden.


123
2018-03-06 15:52


Ursprung




Antworten:


Sie können verwenden watch Befehl, Uhr wird verwendet, um einen bestimmten Befehl in regelmäßigen Intervallen auszuführen.

Öffnen Sie das Terminal und geben Sie Folgendes ein:

watch -n x <your command>

Veränderung x um die Zeit in Sekunden zu sein, die du willst.

Für weitere Hilfe mit dem watch Befehl und seine Optionen ausführen man watch oder besuche dies Verknüpfung.

Beispielsweise : Im Folgenden werden alle aufgelistet 60sim selben Terminal den Inhalt des Desktop-Verzeichnisses, damit Sie wissen, ob Änderungen stattgefunden haben:

watch -n 60 ls -l ~/Desktop

189
2018-03-06 15:54



+1, aber Vorsicht bei der Verwendung von Erweiterungen. Versuchen Sie zum Beispiel den Unterschied zwischen watch -n 1 'echo $COLUMNS' und watch -n 1 echo $COLUMNS Wenn Sie Ihr Terminal in der Größe ändern, wird das Erste jede Sekunde erweitert, aber das Letztere wird nur einmal erweitert Vor  watch beginnt. - l0b0
Niederwähler sollten zumindest einen Befehl hinterlassen, um meine Antwort zu bearbeiten, wenn ich falsch liege - nux
Ich weiß, dass ich ein Pedant und ein Grammatik-Nazi bin, aber die Sprache, die ich auf SE verwende, macht mich verrückt. - Agi Hammerthief
+1 für die Beantwortung der Frage, auch wenn Ihr Englisch nicht zu 100% perfekt ist. - dotancohen
Gibt es eine Möglichkeit zu verwenden? watch mit "history enabled" type Befehl? Ich liebe es zu benutzen watch, aber manchmal würde ich lieber ein Protokoll der vorherigen Ausführungen sehen, anstatt nur das letzte. Und ja, ich weiß, dass ich Scripting verwenden kann (while true), um dies zu erreichen, aber mit der watch Die Nutzung ist so viel sauberer! - rinogo


Sie können diesen Befehl auch im Terminal verwenden, abgesehen von der Antwort von nux:

while true; do <your_command>; sleep <interval_in_seconds>; done

Beispiel

while true; do ls; sleep 2; done

Dieser Befehl druckt die Ausgabe von ls in einem Intervall von 2 Sekunden.

Benutzen Strg+C um den Prozess zu stoppen.

Es gibt einige Nachteile von watch

  • Es kann keine Alias-Befehle verwenden.
  • Wenn die Ausgabe eines Befehls ziemlich lang ist, funktioniert das Scrollen nicht ordnungsgemäß.
  • Es gibt einige Probleme beim Einstellen maximales Zeitintervall jenseits eines bestimmten Wertes.
  • watch interpretiert ANSI-Farbsequenzen, die Escape-Zeichen übergeben -c oder --color Möglichkeit. Zum Beispiel Ausgabe von pygmentize wird funktionieren, aber es wird scheitern ls --color=auto.

Unter den obigen Umständen mag dies als eine bessere Option erscheinen.


75
2018-03-06 16:00



watch existiert dafür, das ist ein bisschen nutzlos, würde ich sagen - Bruno Pereira
Ich behaupte nicht, dass diese Antwort an erster Stelle verwendet werden soll. watch ist in den meisten Fällen gut. Deshalb habe ich am Anfang "abgesehen von der Antwort von Nux" erwähnt. Aber es gibt wenige Probleme mit watch zum Beispiel Eins kann keine Alias-Befehle mit verwenden watch. Nimm zum Beispiel ll was ist Alias ​​zu ls -laF aber kann nicht mit verwendet werden watch. Auch für den Fall, dass die Ausgabe eines Befehls ziemlich lang ist, wird es Probleme beim Scrollen geben watch. In diesen wenigen Sonderfällen scheint diese Antwort eine bessere Option zu sein. - souravc
@souravc Meine Version von watch zumindest erlaubt das -c oder --color Optionen für die kolorierte Ausgabe. - ikdc
while sleep x ist besser - es ist einfacher zu töten. - d33tah
Dies ist eine schöne Alternative und, anders als watch, es behält die Befehlsgeschichte. - adelriosantiago


Ich wollte nur reinhören souravc und NuxAntworten:

  1. Während watch wird auf Ubuntu perfekt funktionieren, du solltest das vermeiden, wenn dein "Unix-Fu" rein sein soll - auf FreeBSD zum Beispiel ist watch ein Befehl, um auf einer anderen TYY-Leitung zu schnüffeln.
  2. while true; do command; sleep SECONDS; done hat auch einen Vorbehalt - Ihr Befehl ist möglicherweise schwerer zu töten CTR + C. Vielleicht möchten Sie bevorzugen while sleep SECONDS; do command; done - Es ist nicht nur kürzer, sondern auch einfacher zu unterbrechen. Der Vorbehalt ist, dass er zuerst schläft und dann deinen Befehl ausführt, also musst du etwas warten SECONDS vor dem ersten Auftreten des Befehls wird passieren.

31
2018-03-08 15:51



Hoffentlich ist es akzeptabel als Antwort statt als Kommentar - ich wollte hier eine andere Lösung zeigen und das Kommentieren würde mir weniger Aufmerksamkeit schenken. - d33tah
Warum genau spielt es eine Rolle, wo du hingehst sleep in dem while Schleife? Ich konnte keinen Unterschied feststellen, Strg + C hat die Schleife durchbrochen sofort egal was. - dessert
@dessert: hängt davon ab, was du ausbrechen willst, denke ich. Normalerweise würde Strg + C nur Ihre töten command und sleep und brich nur wenn du tötest true. - d33tah


Klingt wie die ideale Aufgabe für die cron Daemon, mit dem periodische Befehle ausgeführt werden können. Führen Sie die crontab -e Befehl, um mit der Bearbeitung der Cron-Konfiguration Ihres Benutzers zu beginnen. Sein Format ist in dokumentiert Crontab (5). Im Grunde haben Sie fünf zeitbezogene, durch Leerzeichen getrennte Felder gefolgt von einem Befehl:

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

Wenn Sie beispielsweise an jedem Dienstag um 11 Uhr ein Python-Skript ausführen möchten:

0 11 * * 1 python ~/yourscript.py

Es gibt auch einige spezielle Namen, die die Zeit ersetzen, wie @reboot. Sehr hilfreich, wenn Sie ein temporäres Verzeichnis erstellen müssen. Von meiner Crontab (aufgelistet mit crontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"

11
2018-03-07 18:54



Die Frage fragt, wie im Terminal periodisch etwas ausgeführt werden soll. cron läuft hinter den Kulissen und nicht im Terminal - northern-bradley


Wenn Sie das Dateisystem überwachen, dann inotifywait ist brilliant und bringt sicher weniger Belastung für Ihr System.

Beispiel:

Im 1 Terminal geben Sie diesen Befehl ein:

$ inotifywait .

Dann in 2 terminal, jeder Befehl, der das aktuelle Verzeichnis betrifft,

$ touch newfile

Dann im ursprünglichen Terminal inotifywait aufwachen und das Ereignis melden

./ CREATE newfile2

Oder in einer Schleife

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.

5
2018-03-06 16:35



der Benutzer hat dir gesagt, kein Skript, und vielleicht will er nichts überwachen - nux
Ich habe ihm nicht gesagt, dass er ein Skript schreiben soll. Ich schlug vor, dass, wenn sie eine Schleife bilden, um nach bestimmten Dateisystemereignissen Ausschau zu halten, inotifywait nützlich ist und weniger Ressourcen benötigt, als einen Befehl zu wiederholen. Ich führe oft mehrere Befehle in einer Befehlszeile zB grep something InALogFile|less Ist das ein Skript? - X Tian
es ist eine gute Antwort, versuchen Sie es zu bearbeiten, um einfacher auszusehen. - nux
Was könnte einfacher sein als . Ich kann den Befehl nicht auslassen. - X Tian
Danke @XTian, ​​ein großartiges Kommando. Ich habe jetzt auch in der Manpage gesehen, dass du hinzufügen kannst -m kontinuierlich ohne Schleife zu überwachen. - yoniLavi


Sie können Ihre eigenen erstellen repeat befehle die folgenden Schritte auszuführen; Kredite hier:

Öffne zuerst deine .bash_aliases Datei:

$ xdg-open ~/.bash-aliases

Zweitens, fügen Sie diese Zeilen am Ende der Datei ein und speichern Sie:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

Drittens, entweder schließen und öffnen Sie Ihr Terminal erneut, oder geben Sie Folgendes ein:

$ source ~/.bash_aliases

Et voilà! Sie können es jetzt wie folgt verwenden:

$ repeat 5 echo Hello World !!!

oder

$ repeat 5 ./myscript.sh

4
2017-08-08 19:38



Es gibt einen kleinen Tippfehler in der Zeile xdg-open ~ / .bash-aliases. es sollte sein: xdg-open ~ / .bash_aliases (dh: Unterstrich) - ssinfod


Sie können Crontab verwenden. Führe den Befehl aus crontab -e und öffne es mit deinem bevorzugten Texteditor und füge dann diese Zeile hinzu

*/10 * * * *  /path-to-your-command

Dadurch wird Ihr Befehl alle 10 Minuten ausgeführt

* */4 * * *  /path-to-your-command

Dadurch wird Ihr Befehl alle 4 Stunden ausgeführt

Eine andere mögliche Lösung

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

X Anzahl der Wiederholungen

Y Zeit zu warten, um zu wiederholen.

Beispiel:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done

4
2018-03-07 05:57



Warum ist das eine Verbesserung? Sie haben gerade einen zusätzlichen, überflüssigen Schritt hinzugefügt, indem Sie den Befehl als Variable gespeichert haben. Die einzigen Dinge, die das tut, ist i) es länger zu machen, ii) zwingt Sie, nur einfache Befehle zu verwenden, keine Pipes oder Umleitungen usw. - terdon♦
Entfernen Sie die zusätzliche Variable - Maythux


Ein anderes Problem mit dem oben vorgeschlagenen "Watch" -Ansatz besteht darin, dass das Ergebnis nur dann angezeigt wird, wenn der Prozess abgeschlossen ist. "date; sleep 58; date" zeigt die 2 Daten erst nach 59 Sekunden an ... Wenn Sie etwas starten, das für 4 Minuten läuft, werden langsam mehrere Seiten Inhalt angezeigt, aber Sie werden es nicht wirklich sehen.

Auf der anderen Seite besteht die Sorge mit dem "While" -Ansatz darin, dass die Dauer der Aufgabe nicht berücksichtigt wird.

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

Damit läuft das Skript irgendwann alle paar Minuten, manchmal dauert es 1m40. Selbst wenn ein Cron es alle Minuten ausführen kann, wird es das hier nicht tun.

Um also die Ausgabe der Shell zu sehen, während sie generiert wird, und auf die genaue Anfragezeit zu warten, müssen Sie sich die Zeit vor und nach und die Schleife mit while ansehen.

Etwas wie:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

Dies wird dies ausgeben:

Wie Sie sehen, läuft der Befehl alle Minuten:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

Ersetzen Sie einfach den "Schlaf" echo $(( ( RANDOM % 30 ) + 1 ))"Befehl mit was immer Sie wollen und das wird ausgeführt werden, auf dem Terminal / Shell, genau jede Minute. Wenn Sie einen anderen Zeitplan wollen, ändern Sie einfach die" 60 "Sekunden mit was immer Sie brauchen.

Kürzere Version ohne die Debug-Zeilen:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done

2
2017-12-14 20:56



Auf mich selbst antworten ... Wenn Ihr Befehl mehr als die von Ihnen konfigurierte Verzögerung benötigt, wird $ DELAY einen negativen Wert erhalten und der Schlafbefehl wird fehlschlagen, so dass das Skript sofort neu gestartet wird. Muss sich dessen bewusst sein. - jmspaggi