GNU/Linux >> Linux Esercitazione >  >> Linux

Shell Script while loop:[intorno a una pipeline manca `]'

L'errore è che dovresti rimuovere prima [ perché vuoi controllare lo stato di uscita, quindi usa direttamente il comando.

Le pagine Wiki dello strumento Shellcheck hanno una spiegazione per questo (problema SC1014):

[ .. ] non fa parte della sintassi della shell come if dichiarazioni. Non è equivalente alle parentesi nei linguaggi simili al C, if (foo) { bar; } , e non dovrebbe essere avvolto intorno ai comandi da testare.

[ è solo un normale comando, come whoami o grep , ma con un nome buffo (vedi ls -l /bin/[ ). È una scorciatoia per test .

Se vuoi controllare lo stato di uscita di un certo comando, usa quel comando direttamente.

Se vuoi controllare l'output di un comando, usa "$(..)" per ottenere il suo output, quindi usa test o [ /[[ per fare un confronto tra stringhe:

Usa anche ps aux | grep -q "[r]elayevent.sh" in modo da ottenere lo stato di uscita in silenzio invece di stampare qualsiasi cosa su stdout .

Oppure puoi usare pgrep e indirizza il suo output a /dev/null .

Usa prima la seconda condizione perché sarà più efficiente per l'ultimo caso.

Quindi lo script finale sarà come:

#!/bin/bash
COUNTER=0

while [ "$COUNTER" -lt 10 ] && ps aux | grep -q "[r]elayevent.sh"   ; do

    sleep 3

    let COUNTER+=1

done

Oppure

#!/bin/bash
COUNTER=0

while [ "$COUNTER" -lt 10 ] && pgrep  "[r]elayevent.sh" >/dev/null  ; do

    sleep 3

    let COUNTER+=1

done

Non puoi avere una pipa all'interno di [ ... ] . È anche meglio usare pgrep piuttosto che cercare di analizzare l'output di ps :

count=0
while [ "$count" -lt 10 ] && pgrep relayevent.sh >/dev/null; then
    sleep 3
    count=$(( count + 1 ))
done

I sistemi BSD potrebbero usare pgrep -q ... invece di pgrep ... >/dev/null per scartare l'output effettivo di pgrep , proprio come con il normale grep (siamo interessati solo allo stato di uscita).

Nota come non inseriamo il pgrep comando all'interno di [ ... ] . Questo perché non siamo interessati al suo output, solo al suo stato di uscita. Con [ ... ] di solito confronti stringhe o numeri. Il [ ... ] risulterà in uno stato di uscita che è zero (vero) o diverso da zero (falso), proprio come il pgrep esecuzione.

Tuttavia, questo non controlla alcun meccanismo di blocco, ma solo se un particolare processo è in esecuzione o meno.

Se stai cercando di eseguire solo una singola istanza di uno script, allora è meglio fare qualcosa del genere (supponendo che EXIT trap viene eseguito ogni volta che lo script termina in modo ordinato):

lockdir=dir.lock

if mkdir "$lockdir"; then
    trap 'rmdir "$lockdir"' EXIT
else
    echo 'Only one instance of this script allowed' >&2
    exit 1
fi

Con una serie di tentativi e dormi:

lockdir=dir.lock

count=0
while [ "$count" -lt 10 ]; then
    if mkdir "$lockdir"; then
        trap 'rmdir "$lockdir"' EXIT
        break
    else
        echo 'Locked. Sleeping...' >&2
        sleep 3
    fi

    count=$(( count + 1 ))
done

if [ "$count" -eq 10 ]; then
    echo 'Giving up.' >&2
    exit 1
fi

Correlati:

  • Come assicurarsi che venga eseguita solo un'istanza di uno script bash?

Linux
  1. Preso nel giro? Awk While, Do While, For Loop, Break, Continue, Exit Esempi

  2. Directory corrente dello script Shell?

  3. Perché questa pipeline di shell termina?

  4. Itera sulle righe anziché sulle parole in un ciclo for dello script di shell

  5. restituire il valore dallo script python allo script shell

Bash mentre Loop

Come rendere le variabili d'ambiente "esportate" in uno script di shell?

Timeout in uno script di shell?

Il ciclo while negli script della shell

Come eseguire un comando in uno script della shell?

perché un ciclo while bash non esce durante il piping al sottocomando terminato?