GNU/Linux >> Znalost Linux >  >> Linux

Shell Script while loop:[ kolem potrubí chybí `]'

Chyba je, že byste měli nejprve odstranit [ protože chcete zkontrolovat stav ukončení, pak použijte příkaz přímo.

Wiki stránky nástroje Shellcheck pro to mají vysvětlení (problém SC1014):

[ .. ] není součástí syntaxe shellu jako if prohlášení. Není ekvivalentní k závorkám v jazycích podobných C, if (foo) { bar; } , a neměly by být obalené příkazy k testování.

[ je jen běžný příkaz, jako whoami nebo grep , ale s vtipným názvem (viz ls -l /bin/[ ). Je to zkratka pro test .

Pokud chcete zkontrolovat stav ukončení určitého příkazu, použijte tento příkaz přímo.

Pokud chcete zkontrolovat výstup příkazu, použijte "$(..)" k získání jeho výstupu a poté použijte test nebo [ /[[ provést porovnání řetězců:

Použijte také ps aux | grep -q "[r]elayevent.sh" takže stav ukončení získáte tiše, namísto vytištění čehokoli na stdout .

Nebo můžete použít pgrep a přesměrujte jeho výstup na /dev/null .

Nejprve použijte druhou podmínku, protože v posledním případě bude efektivnější.

Takže konečný skript bude vypadat takto:

#!/bin/bash
COUNTER=0

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

    sleep 3

    let COUNTER+=1

done

Nebo

#!/bin/bash
COUNTER=0

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

    sleep 3

    let COUNTER+=1

done

Uvnitř [ ... ] nemůžete mít trubku . Je také lepší použít pgrep než se pokusit analyzovat výstup ps :

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

BSD systémy by mohly používat pgrep -q ... místo pgrep ... >/dev/null zahodit skutečný výstup pgrep , stejně jako u běžného grep (zajímá nás pouze stav ukončení).

Všimněte si, že nevkládáme pgrep příkaz v rámci [ ... ] . Je to proto, že nás nezajímá jeho výstup, pouze jeho výstupní stav. S [ ... ] běžně porovnáváte řetězce nebo čísla. [ ... ] výsledkem bude stav ukončení, který je nulový (true) nebo nenulový (false), stejně jako pgrep provedení.

To však nekontroluje žádné zamykací mechanismy, pouze to, zda určitý proces běží nebo ne.

Pokud se pokoušíte spustit pouze jednu instanci skriptu, pak je lepší udělat něco takového (za předpokladu EXIT trap se provede vždy, když se skript řádně ukončí):

lockdir=dir.lock

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

S řadou pokusů a spánku:

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

Související:

  • Jak zajistit, aby se spustila pouze jedna instance bash skriptu?

Linux
  1. Upravte skript shellu, když je spuštěn

  2. Aktuální adresář skriptu Shell?

  3. Proč tento plášťový ropovod vystupuje?

  1. Iterujte přes řádky místo slov ve smyčce for shell skriptu

  2. Jak získat výstupní kód vytvořeného procesu ve skriptu očekávaného shellu?

  3. Spuštění pro smyčku z druhého prvku - skript Shell

  1. Jak zajistit, aby byly proměnné prostředí „exportovány“ do skriptu Shell?

  2. Určit prostředí ve skriptu za běhu?

  3. Jak při použití printf uniknout speciálním znakům ve skriptu shellu?