Shell: è possibile ritardare un comando senza usare `sleep`?


21

Ci sono sostituti, alternative o trucchi bash per ritardare i comandi senza usare sleep? Ad esempio, eseguendo il comando seguente senza effettivamente utilizzare la modalità sleep:

$ sleep 10 && echo "This is a test"

42
Cosa c'è che non va sleep?
Muru,

5
Non c'è altra vera ragione se non la curiosità. Ho pensato che sarebbe interessante imparare alcune soluzioni alternative. Penso che atpotrebbe essere uno, ma non sono riuscito a trovare esempi di utilizzo.
user321697

1
@ user321697 “at” è per pianificare singoli lavori. sono eseguiti dal servizio atd, quindi non metteranno in pausa lo script della shell. un caso d'uso per at sarebbe quello di fare qualcosa in un determinato momento (asincrono) e creare un file marker quando è finito, mentre lo script è in attesa che quel file appaia in un ciclo while. potresti ottenere un effetto simile programmando un lavoro per inviare un tuo script a SIGCONT e quindi congelando lo script inviandoti un SIGSTOP.
Grega Bremec,

1
Sono venuto qui aspettandomi che tutti suggerissero uno spinlock. Sono piacevolmente sorpreso da tutte le risposte.
Daan van Hoek,

3
Ri: "Curiosità" - in unix.stackexchange.com/help/dont-ask , osserva il requisito "Dovresti porre solo domande pratiche e rispondenti sulla base di problemi reali che affronti. " - Che questo è stato bene- ricevuto nonostante la contestazione che la linea guida lo rende un'eccezione piuttosto rara.
Charles Duffy,

Risposte:


17

Hai alternative a sleep: Sono ate cron. Contrariamente a sleepquesti, è necessario fornire il momento in cui sono necessari per l'esecuzione.

  • Assicurarsi che il atdservizio sia in esecuzione eseguendo service atd status.
    Ora diciamo che la data è 11:17 UTC; se è necessario eseguire un comando alle 11:25 UTC, la sintassi è: echo "This is a test" | at 11:25.
    Ora tieni presente che atdper impostazione predefinita non registrerà il completamento dei lavori. Per ulteriori informazioni consultare questo link . È meglio che l'applicazione abbia una propria registrazione.

  • È possibile pianificare i lavori in cron, per ulteriori riferimenti: man cronper vedere le sue opzioni o crontab -eper aggiungere nuovi lavori. /var/log/cronpuò essere controllato per le informazioni sull'esecuzione sui lavori.

FYI sleep system call sospende l'esecuzione corrente e pianifica per l'argomento passato ad esso.

MODIFICARE:

Come accennato da @Gaius, puoi anche aggiungere minuti al atcomando, ma diciamo che il tempo è 12:30:30e ora hai eseguito lo scheduler now +1 minutes. Anche se è stato specificato 1 minuto, che si traduce in 60 secondi, atnon attende realmente l' 12:31:30esecuzione del lavoro, ma esegue il lavoro in 12:31:00. Le unità di tempo possono essere minutes, hours, days, or weeks. Per ulteriori informazioni consultareman at

per esempio: echo "ls" | at now +1 minutes


7
Questo non è vero, puoi programmare un lavoro a dire ora +1 minuto, per essere eseguito in pochi minuti
Gaius

29

Con i bashbuiltin puoi fare:

coproc read -t 10 && wait "$!" || true

Dormire per 10 secondi senza usare sleep. Lo coprocè fare in modo che lo readstdin sia una pipa da cui non uscirà mai nulla. || trueè perché lo waitstato di uscita rifletterà un recapito SIGALRM che causerebbe la chiusura della shell se l' errexitopzione è impostata.

In altre conchiglie:

mkshe ksh93hanno sleepincorporato, inutile usare qualcos'altro lì (anche se entrambi supportano anche read -t).

zshsupporta anche read -t, ma ha anche un wrapper integrato in giro select(), quindi puoi anche usare:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

Se quello che vuoi è programmare le cose da eseguire da una sessione di shell interattiva, vedi anche il zsh/schedmodulozsh .


Considereresti read -t 10 < /dev/zero || true?
Jeff Schaller

5
@JeffSchaller Lo eviterei perché è un circuito affollato.
Stéphane Chazelas,

@ StéphaneChazelas Non mi aspetto che sia un circuito affollato - mi aspetto che qualsiasi shell readvenga implementata usando select (2) o qualcosa di simile (implicando che la lettura con timeout sarebbe una buona risposta a questa domanda). Esprimo sorpresa piuttosto che contraddirti, ma puoi indicare ulteriori discussioni su questo?
Norman Gray,

5
@NormanGray, /dev/zeroè un file che contiene una quantità infinita di dati (byte NUL). Quindi readleggerà il più possibile durante quei 10 secondi. Per fortuna, nel caso in bashcui non supporti l'archiviazione di byte NUL nelle sue variabili, ciò non consumerà memoria, ma continuerà a contenere le risorse della CPU.
Stéphane Chazelas,

1
@NormanGray, se eseguito da un terminale, /dev/stdoutsarebbe il dispositivo tty, quindi avrebbe effetti collaterali (come interrompere lo script se eseguito in background) e ritornerebbe se l'utente preme invio per esempio. read -t 10 /dev/stdout | :funzionerebbe su Linux, ma solo su Linux, mentre coprocdovrebbe funzionare indipendentemente dal sistema operativo.
Stéphane Chazelas,

7

Alcune altre idee

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null

1
Hai "rubato" la mia idea di timelimit / timeout .... +1
Rui F Ribeiro

1
Ohhhh, grazie, ero in una situazione senza dormire, la parte superiore è incredibile!
Fire-Dragon-DoL

6

Poiché ci sono risposte che suggeriscono di utilizzare l' -t delayopzione non standard di read, ecco un modo per eseguire una lettura scaduta in una shell standard:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

L'argomento stty timeè in decimi di secondo.


5

Utilizzando la variabile incorporata bash $SECONDSe un ciclo di occupato:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done

2
Ciò in effetti si fermerebbe per una durata compresa tra 9 e 10 secondi (a causa di un bug inbash ; zshe mkshaveva problemi simili ma sono stati risolti da allora)
Stéphane Chazelas

7
Un buon modo per fare calore.
ctrl-alt-delor

6
non sarà la prima volta che sono accusato di essere pieno di aria calda! :)
Jeff Schaller

4

il trucco più antico del libro:

read && echo "This is a test"

Basta colpire Entere continuerà!


Questo non è necessario se il processo deve essere eseguito senza interazione o in background, giusto?
ss_iwe,

Corretto: Ma questo non era uno dei requisiti del PO secondo la domanda originale, quindi una risposta valida ... ;-)> :-)
Fabby

1
OP specifica un esempio (con sleep) e chiede un'alternativa equivalente senza. Quindi readnon analizzare, scusa. ;)
AnoE

@AnoE La risposta di Stéphane è ovviamente la migliore, la mia è solo la più antica --- press «enter» to continue --- ;-)
Fabby

4

Ai tempi dei microcomputer che eseguivano BASIC, i ritardi venivano generalmente eseguiti con un ciclo vuoto:

FOR I = 1 TO 10000:NEXT

Lo stesso principio potrebbe essere utilizzato per inserire un ritardo in uno script di shell:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Naturalmente, il problema con questo approccio è che la lunghezza del ritardo varierà da macchina a macchina in base alla sua velocità del processore (o anche sulla stessa macchina con carichi diversi). Diversamente sleep, probabilmente anche massimizzerà la tua CPU (o uno dei suoi core).


2
Un buon modo per fare calore.
ctrl-alt-delor

2
I delay-loop sono un'idea terribile per qualsiasi cosa tranne il più breve dei sleep (un paio di nanosecondi o cicli di clock in un driver di dispositivo) su qualsiasi CPU moderna in grado di eseguire un sistema operativo simile a Unix. vale a dire una sospensione così breve che non è possibile fare in modo che la CPU faccia altro durante l'attesa, come programmare un altro processo o entrare in uno stato di sospensione a basso consumo prima di svegliarsi su un interruzione del timer. La frequenza dinamica della CPU rende impossibile persino calibrare un loop di ritardo per conteggi al secondo, ad eccezione di un ritardo minimo potenzialmente inattivo molto più a lungo a basse velocità di clock prima di aumentare.
Peter Cordes,

I computer antichi avevano un consumo di energia che era molto meno dipendente dal carico di lavoro. Le CPU moderne hanno bisogno di spegnere dinamicamente il più possibile diverse parti del chip per non sciogliersi (ad esempio spegnere parti della FPU o unità di esecuzione SIMD mentre è in esecuzione solo il codice intero, o almeno trasferire il segnale di clock a parti del chip che non ha bisogno di cambiare). Ed entrare in uno stato di sospensione a basso consumo quando il minimo (invece di girare in un ciclo infinito in attesa di interruzioni del timer) è anche più recente degli antichi computer che menzioni.
Peter Cordes,

Per ulteriori informazioni sulla cronologia della CPU, consultare la Guida ai 90 microprocessori moderni! - lighterra.com/papers/modernmicroprocessors .
Peter Cordes,

3

Non esiste un built-in, che fa lo stesso di sleep(a meno che non sleepsia incorporato). Tuttavia ci sono alcuni altri comandi che aspetteranno.

Alcuni includono.

  • ate cron: utilizzato per pianificare le attività in un momento specifico.

  • inotifywait: utilizzato per attendere che un file o i file vengano modificati / rimossi / aggiunti / ecc


Grazie per questo. Potresti fornire un esempio per eseguire un'attività pianificata (tra 10 secondi da ora) con at?
user321697

1
una modifica e un voto! ;-)
Fabby,

cronarchiviare le attività crontab, giusto? Dove vengono atarchiviati i dati programmati?
user321697

@ user321697 Già risposto qui
Fabby

Mi dispiace per aver ripristinato la tua modifica in Q: hai cambiato lo scopo principale della domanda OP che invaliderebbe la risposta più semplice di tutte ... ¯ \ _ (ツ) _ / ¯
Fabby

3

Un classico dalla terra di Windows e batch:

ping -c 11 localhost >/dev/null && echo "This is a test"

La configurazione errata del firewall o del sistema dei nomi potrebbe introdurre un notevole ritardo aggiuntivo.
extra

1
127.0.0.1 ... @spectras
AnoE

1
Per fortuna non è più necessario, poiché Windows ora supporta il sonno in modo nativo.
Baldrickk,

1
@AnoE> risolve la parte del sistema dei nomi, non la parte del firewall. Sebbene non sia comune, può essere configurato per rilasciare silenziosamente ping sull'interfaccia locale. Ciò farà attendere il ping molto più a lungo.
extra

+1 per i ricordi "affettuosi"
AC

0

Se vuoi aspettare interattivamente una nuova riga in un file, allora

tail -f
.

In attesa di una modifica su un filesystem? Quindi utilizzare ad es

inotify / inoticoming
.

E ci sono altre opzioni, a seconda di cosa intendi con "wait".

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.