Is er iets vergelijkbaars met pipefail voor meerdere commando's, zoals een 'try' statement maar dan binnen bash. Ik zou graag zoiets als dit willen doen:
echo "trying stuff"
try {
command1
command2
command3
}
En op elk moment, als een commando faalt, afhaken en de fout van dat commando echoën. Ik wil niet dat ik iets moet doen als:
command1
if [ $? -ne 0 ]; then
echo "command1 borked it"
fi
command2
if [ $? -ne 0 ]; then
echo "command2 borked it"
fi
En zo verder... of iets dergelijks:
pipefail -o
command1 "arg1" "arg2" | command2 "arg1" "arg2" | command3
Omdat de argumenten van elk commando geloof ik (corrigeer me als ik'me vergis) met elkaar zullen interfereren. Deze twee methodes lijken me verschrikkelijk langdradig en vervelend, dus ik'doe hier een oproep voor een efficiëntere methode.
Je kunt een functie schrijven die het commando voor je start en test. Stel dat command1
en command2
omgevingsvariabelen zijn die zijn ingesteld op een commando.
function mytest {
"$@"
local status=$?
if [ $status -ne 0 ]; then
echo "error with $1" >&2
fi
return $status
}
mytest $command1
mytest $command2
Wat bedoel je met "drop out and echo the error"? Als je bedoelt dat je het script wilt laten eindigen zodra een commando mislukt, doe dan gewoon
set -e # DON'T do this. See commentary below.
aan het begin van het script (maar let op de waarschuwing hieronder). Doe geen moeite om de foutmelding te echoën: laat het falende commando dat afhandelen. Met andere woorden, als je dat doet:
#!/bin/sh
set -e # Use caution. eg, don't do this
command1
command2
command3
en commando2 faalt, terwijl een foutmelding naar stderr wordt geprint, dan lijkt het erop dat je hebt bereikt wat je wilt. (Tenzij ik verkeerd interpreteer wat je wilt!)
Een gevolg hiervan is dat elk commando dat je schrijft zich goed moet gedragen: het moet fouten melden op stderr in plaats van stdout (de voorbeeldcode in de vraag drukt fouten af op stdout) en het moet afsluiten met een niet-nul status als het mislukt.
Ik beschouw dit echter niet langer als een goede praktijk. set -e
heeft zijn semantiek veranderd met verschillende versies van bash, en hoewel het prima werkt voor een eenvoudig script, zijn er zo veel randgevallen dat het in wezen onbruikbaar is. (Denk aan dingen als: set -e; foo() { false; echo should not print; } ; foo && echo ok
De semantiek hier is enigszins redelijk, maar als je code refactored in een functie die afhankelijk was van de optie-instelling om vroegtijdig te eindigen, kun je gemakkelijk gebeten worden). IMO is het beter om te schrijven:
#!/bin/sh
command1 || exit
command2 || exit
command3 || exit
of
#!/bin/sh
command1 && command2 && command3