Rieseguire continuamente un comando al termine in Bash


62

Sto cercando di capire un modo semplice per continuare a rieseguire un comando ogni volta che finisce, per qualsiasi motivo (errore o altro).

Quale sarebbe il modo migliore per affrontare questo?

EDIT: non ero abbastanza chiaro prima. Ho bisogno della prossima esecuzione per aspettare fino a quando la precedente termina.

EDIT 2: quasi tutte le risposte funzionano alla grande. Ho erroneamente pensato che la maggior parte delle risposte avrebbe rovesciato il processo o rieseguito una sola volta, nessuna delle quali è richiesta.

linux  bash 

1
Non sei ancora chiaro. Sarebbe utile se menzionassi quale programma stai eseguendo.
Daniel Beck

1
-1 Questa domanda non mostra alcuno sforzo di ricerca, in quanto l'utente ha commentato che le risposte non hanno funzionato invece di provare effettivamente a fare ciò che suggeriscono.
Daniel Beck

Risposte:


39

Questo crea un ciclo infinito, eseguendo commandpiù e più volte.

while :
    do
        command
done

Si prega di vedere la modifica alla domanda originale. Devo continuare a rieseguirlo più volte, non solo una volta.

8
@calcifer Questa risposta funziona abbastanza bene. C'è qualcosa di insolito nel tuo programma che nessuno dei quattro utenti ha risposto fino a quel momento e che non hai menzionato.
Daniel Beck

@calcifer questo è un ciclo infinito. continua a ripetersi fino alla fine dei tempi (beh, fino a quando la sceneggiatura non viene comunque terminata)
Nate Koppenhaver,

1
Mio male, ho pensato che questo (e tutte le altre risposte) o rovineranno il processo o lo eseguiranno solo una volta, nessuna delle quali è richiesta. Quindi sì, questa risposta funziona. Grazie.

1
versione a una riga: while true; do echo 'Hit CTRL+C'; sleep 1; donegrazie a cyberciti.biz/faq/bash-infinite-loop
jk2K

107

Il watchcomando ripeterà un comando per sempre con un intervallo specificato:

watch -n0 <command>

L'impostazione -nsu zero mette effettivamente a zero l'intervallo (penso che sia davvero 0 secondi).

watch ha anche l'ulteriore vantaggio di allineare l'output in modo da poter vedere facilmente i cambiamenti visivi e ha un interruttore per evidenziare i cambiamenti dall'ultima corsa.

Riferimento: la pagina man watch :

watch esegue ripetutamente il comando, visualizzando il suo output (il primo schermo). Ciò consente di guardare l'output del programma cambiare nel tempo. Per impostazione predefinita, il programma viene eseguito ogni 2 secondi; usare -n o --interval per specificare un intervallo diverso.

l'orologio funzionerà fino all'interruzione.


Si prega di vedere la modifica alla domanda originale.

6
Tutte le risposte finora lo fanno, incluso questo. Linux non si biforcherà a meno che tu non lo chieda espressamente.
Paolo,

Non lo sapevo della forcella, grazie.

Non riesco a vedere alcun output utilizzando questo metodo.
Raffi Khatchadourian

@RaffiKhatchadourian Stai dicendo che se lo fai watch lsin una directory che contiene file, non ottieni nulla?
Paul

17

Una soluzione semplice sarebbe:

yourcommand; !#

;separa i comandi, consentendo più comandi in una riga ( Bash: Liste )

!#dice a bash di "ripetere tutto ciò che ho scritto finora in questa riga" ( Bash: Event-Designators )


1
Scusa, non ero abbastanza chiaro. Devo continuare a rieseguirlo più volte, non solo una volta.

Grazie per questo, lo stavo cercando, soprattutto perché in yourcommand; !!realtà non funziona con i comandi sulla stessa linea, tuttavia !#sembra funzionare. Saluti!
sdaau,

; !#non ha funzionato su ZSH, si limita a espandere la dichiarazione essenzialmente clonandola, non la attiva
rinnovato

7

È possibile pianificare in anticipo durante l'esecuzione del comando (a condizione che non sia interattivo) e immettere !!quale eseguirà nuovamente il comando precedente. Questo funziona ad es ping -c 5. Durante .


Puoi anche definire una funzione in bash:

function repeat { "$@"; "$@"; }

Per persistere, conservalo in ~/.bashrc.

Quindi, puoi eseguire il comando in questo modo:

repeat ping -c5 heise.de

Se si tratta di un comando specifico che si desidera eseguire ripetutamente (e non ad esempio alcun comando), è possibile sostituire "$@"in quello snippet con il comando effettivo e nominare invece la funzione ad es repeat_ping.


Per renderlo un ciclo infinito, puoi fare ciò che suggerisce @Dennis. Ti consiglio di aggiungere un periodo di attesa se intendi utilizzarlo in una shell interattiva, in questo modo:

function repeat { while 1 ; do "$@" ; sleep 1 ; done; }

Altrimenti è piuttosto scomodo interrompere questo ciclo infinito usando Ctrl-Z.


Si prega di vedere la modifica alla domanda originale.

6
@calcifer Queste esecuzioni attendono il ritorno della chiamata al programma. Il programma si stacca dalla shell e ritorna prima che si chiuda?
Daniel Beck

Mio male, ho pensato che questo (e tutte le altre risposte) o rovineranno il processo o lo eseguiranno solo una volta, nessuna delle quali è richiesta. Quindi sì, questa risposta funziona. Grazie.

4

Assegna a un whileloop una condizione booleana come la seguente:

#!/bin/bash

while true; do

    do_something && wait

done

Questo verrà eseguito più volte fino a quando bash non riceve un segnale per terminare il processo. Di solito sotto forma di ctrl+c.

Puoi anche usare il watchcomando per eseguire ripetutamente uno script. Ad esempio, un semplice orologio nel tuo terminale bash watchpotrebbe apparire come:

$ watch -t -n1 date +%T

L' -topzione dice watchdi non visualizzare un titolo del processo in esecuzione. Questo ti dà un output pulito del solo comando che viene ripetuto. L' -n1opzione dice all'orologio di ripetere ogni nsecondo. In questo caso, -n1saranno gli intervalli del 1secondo. Quindi il date +%Tcomando mostra l'ora al momento del completamento del comando. L'esecuzione di questo comando ti darà un orologio attivo nel tuo terminale.

E poi un altro metodo che non è presente in nessuna delle altre risposte sarebbe una chiamata di funzione infinita.

do_something() { do_something }; do_something && wait

Questo è essenzialmente lo stesso del whileciclo booleano che utilizza solo chiamate di funzione ricorsive.

(modifica) Per tenere a mente le risorse della macchina, ho aggiunto && waitche ogni volta che viene eseguito un processo, i loop "attendono" fino a quando il processo termina con lo stato di uscita 0 prima della successiva iterazione. Ciò è utile in uno script di shell interattivo.


1
C'è un whileesempio di loop ma non utilizza una truesintassi booleana . C'è un watchesempio ma non fornisce molte utili sintassi. Sto spiegando queste cose per chiunque possa essere d'aiuto. Volevo dare una certa utilità pratica a questi. Il whileloop booleano può anche essere falsee non essere eseguito fino a quando non viene soddisfatta una condizione non vera. È abbastanza utile.

1
@ Spittin'IT Aggiunto un metodo che non viene utilizzato in altre risposte per comodità.

Abbastanza giusto e capisco ... stavo solo commentando mentre passavo attraverso il modulo di recensione, ma bella modifica e follow-up !!
Pimp Juice IT

Come si ifcontinua a rieseguire?
Kamil Maciorowski,

Buon punto Kamil. Ho dimenticato di renderlo ricorsivo lol. Risolto in modifica usando una funzione che si richiamava ifnell'istruzione.

0

Questo è un altro metodo che uso per ripetere un comando in bash. Questo potrebbe sembrare sciocco per alcuni in quanto non comporta la scrittura di una sceneggiatura e potrebbe essere noto a molti. Ma penso che valga la pena menzionarlo poiché è veloce e adatto ai principianti, nel senso che non c'è molta sintassi da ricordare. L'ho provato solo nel terminale GNOME di Ubuntu e altri terminali potrebbero non supportarlo.

  1. Immettere il comando nel terminale una volta.
  2. Seleziona il comando incluso il carattere di nuova riga con il mouse.
  3. Copia la selezione usando Ctrl-Inserisci o usando il menu contestuale (di solito si accede con il tasto destro del mouse).
  4. Utilizzare Maiusc-Inserisci per incollare tutte le volte che si desidera eseguire il comando.

Non devi aspettare di incollare fino al termine di ciascun comando. I comandi incollati entrano in una coda e si eseguono uno dopo l'altro.


0

Mi sento impertinente oggi.

Leggi da uno dei flussi infiniti e instradalo a xargs

cat /dev/zero | xargs --null echo hello there

Se hai bisogno di fare un po 'di pausa, probabilmente dovrai eseguire sh

cat /dev/zero | xargs --null sh -c "echo hello there && sleep 3"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.