GNU/Linux >> Linux Esercitazione >  >> Linux

Timeout in uno script di shell?

Ho uno script di shell si tratta di leggere dallo standard input . In rare circostanze, non ci sarà nessuno pronto a fornire input e lo script deve scadere . In caso di timeout, lo script deve eseguire del codice di pulizia. Qual è il modo migliore per farlo?

Questo script deve essere molto portabile , inclusi i sistemi Unix del 20° secolo senza un compilatore C e i dispositivi embedded che eseguono busybox, quindi non è possibile fare affidamento su Perl, bash, qualsiasi linguaggio compilato e persino l'intero POSIX.2. In particolare, $PPID , read -t e non sono disponibili trappole perfettamente conformi a POSIX. È esclusa anche la scrittura su un file temporaneo; lo script potrebbe essere eseguito anche se tutti i filesystem sono montati in sola lettura.

Per rendere le cose più difficili, voglio anche che la sceneggiatura sia ragionevolmente veloce quando non è scaduto. In particolare, utilizzo lo script anche in Windows (principalmente in Cygwin), dove fork ed exec sono particolarmente bassi, quindi voglio mantenerne l'utilizzo al minimo.

In poche parole, ho

trap cleanup 1 2 3 15
foo=`cat`

e voglio aggiungere un timeout. Non posso sostituire cat con il read incorporato. In caso di timeout, voglio eseguire la cleanup funzione.

Sfondo:questo script sta indovinando la codifica del terminale stampando alcuni caratteri a 8 bit e confrontando la posizione del cursore prima e dopo. L'inizio dello script verifica che stdout sia connesso a un terminale supportato, ma a volte l'ambiente sta mentendo (ad es. plink imposta TERM=xterm anche se viene chiamato con TERM=dumb ). La parte rilevante dello script si presenta così:

text='Éé'  # UTF-8; shows up as Ãé on a latin1 terminal
csi='␛['; dsr_cpr="${csi}6n"; dsr_ok="${csi}5n"  # ␛ is an escape character
stty_save=`stty -g`
cleanup () { stty "$stty_save"; }
trap 'cleanup; exit 120' 0 1 2 3 15     # cleanup code
stty eol 0 eof n -echo                # Input will end with `0n`
# echo-n is a function that outputs its argument without a newline
echo-n "$dsr_cpr$dsr_ok"              # Ask the terminal to report the cursor position
initial_report=`tr -dc ;0123456789`  # Expect ␛[42;10R␛[0n for y=42,x=10
echo-n "$text$dsr_cpr$dsr_ok"
final_report=`tr -dc ;0123456789`
cleanup
# Compute and return initial_x - final_x

Come posso modificare lo script in modo che se tr non ha letto alcun input dopo 2 secondi, viene terminato e lo script esegue la cleanup funzione?

Risposta accettata:

Che ne dici di questo:

foo=`{ { cat 1>&3; kill 0; } | { sleep 2; kill 0; } } 3>&1`

Cioè:esegui il comando di produzione dell'output e sleep nello stesso gruppo di processi, un gruppo di processi solo per loro. Qualunque comando venga restituito per primo, uccide l'intero gruppo di processi.

Qualcuno si chiederebbe:Sì, il tubo non viene utilizzato; viene bypassato utilizzando i reindirizzamenti. L'unico scopo è che la shell esegua i due processi nello stesso gruppo di processi.

Correlati:uno script per ridurre e comprimere le immagini del disco DMG non sembra funzionare bene nello scenario?

Come ha sottolineato Gilles nel suo commento, questo non funzionerà in uno script di shell perché il processo di script verrebbe interrotto insieme ai due sottoprocessi.

Un modo¹ per forzare l'esecuzione di un comando in un gruppo di processi separato consiste nell'avviare una nuova shell interattiva:

#!/bin/sh
foo=`sh -ic '{ cat 1>&3; kill 0; } | { sleep 2; kill 0; }' 3>&1 2>/dev/null`
[ -n "$foo" ] && echo got: "$foo" || echo timeouted

Ma potrebbero esserci degli avvertimenti con questo (ad esempio quando stdin non è un tty?). Il reindirizzamento stderr serve per eliminare il messaggio "Terminated" quando la shell interattiva viene terminata.

Testato con zsh ,bash e dash . Ma che dire dei vecchi?

B98 suggerisce la seguente modifica, lavorando su Mac OS X, con GNU bash 3.2.57, o Linux con dash:

foo=`sh -ic 'exec 3>&1 2>/dev/null; { cat 1>&3; kill 0; } | { sleep 2; kill 0; }'`



Linux
  1. Determinare la shell nello script durante il runtime?

  2. Determinazione del percorso per lo script della shell di origine?

  3. Come gestire gli interruttori in uno script di shell?

  4. Processi in una sessione in una shell interattiva vs in uno script?

  5. Il significato di $? In uno script di shell?

Come utilizzare le variabili negli script della shell

Come creare script di shell

Come eseguire un comando in uno script della shell?

Un file .sh può essere un malware?

determinare la shell nello script durante il runtime

Eseguire uno script di shell come utente diverso