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 jakoif
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, jakowhoami
nebogrep
, ale s vtipným názvem (vizls -l /bin/[
). Je to zkratka protest
.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žijtetest
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?