Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Waarom wordt de foutcode niet bewaard

3 views
Skip to first unread message

Cecil Westerhof

unread,
Nov 5, 2023, 4:28:05 PM11/5/23
to
Als ik doe:
echo $((1 / 0)) || :
echo ${?}

Dan krijg ik:
1

Als ik echter doe:
sa-update || :
echo ${?}

Dan krijg ik:
0

Terwijl:
sa-update
echo ${?}

oplevert:
1

Waarom wordt in het eerste geval de foutcode wel bewaard en in het
tweede geval niet?

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

Cecil Westerhof

unread,
Nov 5, 2023, 4:59:15 PM11/5/23
to
Cecil Westerhof <Ce...@decebal.nl> writes:

> Als ik doe:
> echo $((1 / 0)) || :
> echo ${?}
>
> Dan krijg ik:
> 1
>
> Als ik echter doe:
> sa-update || :
> echo ${?}
>
> Dan krijg ik:
> 0
>
> Terwijl:
> sa-update
> echo ${?}
>
> oplevert:
> 1
>
> Waarom wordt in het eerste geval de foutcode wel bewaard en in het
> tweede geval niet?

Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
het verschil bij de bovenstaande commando's.

Oplossing:
sa-update && retVal=${?} || retVal=${?}

Richard Lucassen

unread,
Nov 6, 2023, 2:06:28 AM11/6/23
to
On Sun, 05 Nov 2023 22:56:24 +0100
Cecil Westerhof <Ce...@decebal.nl> wrote:

> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
> het verschil bij de bovenstaande commando's.
>
> Oplossing:
> sa-update && retVal=${?} || retVal=${?}

sa-update
EXITCODE=$?
<verdere code>
echo "de exitcode van sa-update is ${EXITCODE}"

M.a.w.: stop de exitcode direct in een var. Dan raak je die niet meer
kwijt. Dan vang je ook meteen alle andere exitcodes (dus niet 0 of 1)
af, zoals bij wget of rsync.

--
Richard Lucassen <mailin...@lucassen.org>

De ongekruisigde

unread,
Nov 6, 2023, 4:42:23 AM11/6/23
to
On 2023-11-05, Cecil Westerhof <Ce...@decebal.nl> wrote:
> Cecil Westerhof <Ce...@decebal.nl> writes:
>
>> Als ik doe:
>> echo $((1 / 0)) || :
>> echo ${?}
>>
>> Dan krijg ik:
>> 1
>>
>> Als ik echter doe:
>> sa-update || :
>> echo ${?}
>>
>> Dan krijg ik:
>> 0
>>
>> Terwijl:
>> sa-update
>> echo ${?}
>>
>> oplevert:
>> 1
>>
>> Waarom wordt in het eerste geval de foutcode wel bewaard en in het
>> tweede geval niet?
>
> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
> het verschil bij de bovenstaande commando's.

weet je dat echt niet? ( hint: tik eens which true )


> Oplossing:
> sa-update && retVal=${?} || retVal=${?}

dat is een lelijke workaround voor een non-problem

Cecil Westerhof

unread,
Nov 6, 2023, 5:14:05 AM11/6/23
to
Oeps, belangrijk onderdeel vergeten te noemen. 🥵
Ik gebruik in (bijna al) mijn scripts:
set -o errexit

Dat was waarom ik aan het truken was.

De ongekruisigde

unread,
Nov 6, 2023, 5:43:15 AM11/6/23
to
On 2023-11-06, Cecil Westerhof <Ce...@decebal.nl> wrote:
> Richard Lucassen <mailin...@lucassen.org> writes:
>
>> On Sun, 05 Nov 2023 22:56:24 +0100
>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>
>>> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
>>> het verschil bij de bovenstaande commando's.
>>>
>>> Oplossing:
>>> sa-update && retVal=${?} || retVal=${?}
>>
>> sa-update
>> EXITCODE=$?
>> <verdere code>
>> echo "de exitcode van sa-update is ${EXITCODE}"
>>
>> M.a.w.: stop de exitcode direct in een var. Dan raak je die niet meer
>> kwijt. Dan vang je ook meteen alle andere exitcodes (dus niet 0 of 1)
>> af, zoals bij wget of rsync.
>
> Oeps, belangrijk onderdeel vergeten te noemen. 🥵
> Ik gebruik in (bijna al) mijn scripts:
> set -o errexit

lees dan dit nog maar eens goed door:

https://stackoverflow.com/questions/44080974/if-errexit-is-on-how-do-i-run-a-command-that-might-fail-and-get-its-exit-code


> Dat was waarom ik aan het truken was.

knoeien

Oscar

unread,
Nov 6, 2023, 8:44:30 AM11/6/23
to
In article <87bkc79...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>Als ik doe:
> echo $((1 / 0)) || :
> echo ${?}

Waarom "of niks" er achter? 'help :' zegt dat die laatste altijd true
returned, dus je zou verwachten dat die 'echo $?' altijd 0 geeft.

Maar!

De shell ziet een '||' met twee commando's er omheen. Voordat hij de
commando's kan uitvoeren, moet ie eerst de regel evalueren. Bij dat
evalueren gaat het al hartstikke fout, want je deelt daarbij door 0.

De hele regel is dus niet eens aan het uitvoeren toegekomen. Kijk maar
eens wat er gebeurt als je

foobar $((1/0))

uitvoert. Je zou misschien verwachten:

foobar: command not found

maar je krijgt:

bash: 1/0: division by 0 (error token is "0")

Leermoment: de evaluatie van de regel gebeurt in de huidige shell,
voordat de regel uitgevoerd wordt. Het is dus niet 'echo' die in je
voorbeeld een fout returnt, het is bash die op zijn bek gaat.

>Dan krijg ik:
> 1

Klopt. Het uitvoeren van de voorgaande regel heeft een foutcode gezet.

>Als ik echter doe:
> sa-update || :
> echo ${?}
>
>Dan krijg ik:
> 0

Ook dat klopt. Als 'sa-update' zelf 0 terug had gegeven, dan is de regel
klaar en is je $? gezet door sa-update. Als die echter een error had
gegeven, dan was het tweede deel van de 'or' uitgevoerd. Daar heb je een
':' staan wat altijd 0 returned. Zie 'help :' in bash. De $? in je echo
komt dan van de : vandaan. Je krijgt dus altijd 0.

Voor wie het nog niet weet, maar wel ervaring heeft in andere talen: In
bash betekend 0 hetzelfde als True en non-zero is dan False. De 0 staat
simpelweg voor: "Geen fout" of "Succes". De booleanse logica blijft
verder hetzelfde.

>Terwijl:
> sa-update
> echo ${?}
>
>oplevert:
> 1

Dan zal sa-update een exitcode van 1 hebben gehad. Heel logisch. ;-)

Ik snap eigenlijk niet helemaal waarom je de accolades om de ? heen zet.
Het mag, maar het lijkt mij hier overbodig en ietwat verwarrend.
--
[J|O|R] <- .signature.gz

Oscar

unread,
Nov 6, 2023, 8:47:37 AM11/6/23
to
In article <uiacdu$du7i$1...@dont-email.me>,
De ongekruisigde <verstotene@invalid> wrote:
>> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
>> het verschil bij de bovenstaande commando's.
>
>weet je dat echt niet? ( hint: tik eens which true )

Wat een ontzettend nutteloos en ook nog eens fout antwoord.

Wat heeft het pad naar 'true' te maken met zijn probleem?
Leg dat eens uit?

Oscar

unread,
Nov 6, 2023, 8:50:18 AM11/6/23
to
In article <874jhz9...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>Oplossing:
> sa-update && retVal=${?} || retVal=${?}

De oplossing voor welk probleem was dat dan?

Dit werkt net zo goed:

sa-update
retVal=$?

Of als je het graag in 1 regel wil:

sa-update; retVal=$?

Oscar

unread,
Nov 6, 2023, 9:06:01 AM11/6/23
to
In article <uiag01$efja$1...@dont-email.me>,
De ongekruisigde <verstotene@invalid> wrote:
>On 2023-11-06, Cecil Westerhof <Ce...@decebal.nl> wrote:
>> Oeps, belangrijk onderdeel vergeten te noemen. 🥵
>> Ik gebruik in (bijna al) mijn scripts:
>> set -o errexit

Oh, aha. Dan snap ik je probleem.
Dit is zowaar een bruikbare tip van De ongekruisigde.

Maar nou is mijn vraag: heb je retVal echt nodig, ook als het goed gaat?

Zou je het zelfs zonder retVal afkunnen met deze leesbaardere
constructie:

if sa-update
then
# doe wat nodig is als sa-update goed gaat
else
# doe de foutafhandeling
fi

Jouw eerdere 'sa-update && retVal=0 || retVal=$?' zou je ook zo kunnen
schrijven:

if sa-update
then
retVal=0
else
retVal=$?
fi

En dat is eigenlijk net zo'n rare work-around. En al helemaal als je 2
keer 'retVal=$?' schijft, ook waar die altijd 0 zal zijn.

De ongekruisigde

unread,
Nov 6, 2023, 10:05:40 AM11/6/23
to
On 2023-11-06, Oscar <jornws...@xs4all.nl> wrote:
> In article <uiacdu$du7i$1...@dont-email.me>,
> De ongekruisigde <verstotene@invalid> wrote:
>>> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
>>> het verschil bij de bovenstaande commando's.
>>
>>weet je dat echt niet? ( hint: tik eens which true )
>
> Wat een ontzettend nutteloos en ook nog eens fout antwoord.

Nou... Als je niet beseft dat : voor true staat en dat true
gewoon een commando is dat in een waarde in ${?} resulteert dan
zou je misschien op het spoor van Cecil eindigen. Kortom: niet
fout maar simpelweg een hint (die je wel degelijk op het goede
spoor zou kunnen zetten).


> Wat heeft het pad naar 'true' te maken met zijn probleem?
> Leg dat eens uit?

Niet het pad naar true maar het feit dat je uit het bestaan van
dat pad kan afleiden true geen shell built-in is maar een extern
commando dat een resultaat code in ${?} zet. Enigszins cryptisch
misschien maar komaan zeg, welk niveau heeft men hier (*)?


(*) uit jouw uitleg in een ander antwoord leid ik af dat jij in
deze wel weet waarover je 't hebt.

Cecil Westerhof

unread,
Nov 6, 2023, 10:14:10 AM11/6/23
to
Daar heb ik bovenstaande oplossing vandaan. :-)

Maar dit is misschien een betere oplossing (duidelijker):
if sa-update ; then retVal=0 ; else retVal=${?} ; fi

Eigenlijk heb ik een grondige hekel aan 1-regelige if statements, maar
in dit specifieke geval ben ik bereid een uitzondering te maken.

De ongekruisigde

unread,
Nov 6, 2023, 10:17:57 AM11/6/23
to
On 2023-11-06, Cecil Westerhof <Ce...@decebal.nl> wrote:
> De ongekruisigde <verst...@news.eternal-september.org> writes:
>
>> On 2023-11-06, Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> Richard Lucassen <mailin...@lucassen.org> writes:
>>>
>>>> On Sun, 05 Nov 2023 22:56:24 +0100
>>>> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>>>
>>>>> Ik heb een oplossing gevonden, maar ik ben nog steeds benieuwd naar
>>>>> het verschil bij de bovenstaande commando's.
>>>>>
>>>>> Oplossing:
>>>>> sa-update && retVal=${?} || retVal=${?}
>>>>
>>>> sa-update
>>>> EXITCODE=$?
>>>> <verdere code>
>>>> echo "de exitcode van sa-update is ${EXITCODE}"
>>>>
>>>> M.a.w.: stop de exitcode direct in een var. Dan raak je die niet meer
>>>> kwijt. Dan vang je ook meteen alle andere exitcodes (dus niet 0 of 1)
>>>> af, zoals bij wget of rsync.
>>>
>>> Oeps, belangrijk onderdeel vergeten te noemen. 🥵
>>> Ik gebruik in (bijna al) mijn scripts:
>>> set -o errexit

Misschien is een shell script linter een beter idee dan die errexit?

https://blog.davidjeddy.com/2018/11/27/using-shellcheck-to-lint-your-bash-sh-scripts/


>>
>> lees dan dit nog maar eens goed door:
>>
>> https://stackoverflow.com/questions/44080974/if-errexit-is-on-how-do-i-run-a-command-that-might-fail-and-get-its-exit-code
>
> Daar heb ik bovenstaande oplossing vandaan. :-)


> Maar dit is misschien een betere oplossing (duidelijker):
> if sa-update ; then retVal=0 ; else retVal=${?} ; fi
>
> Eigenlijk heb ik een grondige hekel aan 1-regelige if statements, maar
> in dit specifieke geval ben ik bereid een uitzondering te maken.

mij staat vooral dat tweemaal toekennen aan retVal tegen, een
non-problem wat alleen door die errexit noodzakelijk is

Oscar

unread,
Nov 6, 2023, 10:31:25 AM11/6/23
to
In article <uiavc3$gofd$1...@dont-email.me>,
De ongekruisigde <verstotene@invalid> wrote:
>>>weet je dat echt niet? ( hint: tik eens which true )
>> Wat een ontzettend nutteloos en ook nog eens fout antwoord.
>Nou... Als je niet beseft dat : voor true staat en dat true
>gewoon een commando is dat in een waarde in ${?} resulteert dan
>zou je misschien op het spoor van Cecil eindigen.

Waarom zou `which true` Cecil op het spoor kunnen brengen?

Met 'which' zoek je via het pad naar 'true' waardoor je uitkomt
op /bin/true. Dat is een externe executable die interdaad niet veel meer
doet dan een 0 als exit value. Dit in tegenstelling tot de : wat een
shell builtin van bash is. Net als 'true' trouwens. Kijk maar eens wat
'type true' oplevert.

Net als bijvoorbeeld echo heb je dus twee varianten. De builtin van bash
(die je krijgt als je 'echo' zonder pad gebruikt) en /bin/echo.

Maar dan komen we bij ':'. Jij zegt dat nu dat voor true staat, maar dat
klopt ook al niet, hoewel dat meer een semantische kwestie is. Kijk maar:

$ help true
true: true
Return a successful result.

Exit Status:
Always succeeds.

$ help :
:: :
Null command.

No effect; the command does nothing.

Exit Status:
Always succeeds.

Zoals je ziet heeft 'true' een functie. Het returned expliciet 'Success'.
De : daarentegen is een 'null command', dat altijd succesvol afloopt.

Het effect is hetzelfde. Cecil had dus ook 'sa-update || true' kunnen
schrijven. Ik vind zelfs dat dat minder cryptisch is, dus beter.

Maar dan nog. Zelfs al zou enige variant /bin/true aanroepen, dan nog
was dat niet het antwoord op de vraag waarom de resultaten verschillen.

Het enige juiste antwoord heb ik daarnet gegeven. Het verschil komt
doordat bash zelf al een fout geeft op het evalueren van $((1/0))
voordat de regel uitgevoerd kan worden.

Daar verandert geen 'which /bin/true' iets aan.

>Niet het pad naar true maar het feit dat je uit het bestaan van
>dat pad kan afleiden true geen shell built-in is maar een extern
>commando dat een resultaat code in ${?} zet. Enigszins cryptisch
>misschien maar komaan zeg, welk niveau heeft men hier (*)?

Het is dus niet eens een extern commando. En de hint leidt af van het
werkelijke probleem. Ook al vervang je alle dubbele punten door
/bin/true, dan nog krijg je het merkwaardige verschil tussen beide
varianten.

>(*) uit jouw uitleg in een ander antwoord leid ik af dat jij in
>deze wel weet waarover je 't hebt.

Dank. :-)

Cecil Westerhof

unread,
Nov 6, 2023, 10:44:04 AM11/6/23
to
jornws...@xs4all.nl (Oscar) writes:

> In article <874jhz9...@munus.decebal.nl>,
> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>Oplossing:
>> sa-update && retVal=${?} || retVal=${?}
> De oplossing voor welk probleem was dat dan?

Dat ik in eigenlijk al mijn script heb:
set -o errexit

En ik moet de return code van sa-update hebben en voorkomen dat mijn
script wordt getermineerd als die niet 0 is.


> Dit werkt net zo goed:
>
> sa-update
> retVal=$?
>
> Of als je het graag in 1 regel wil:
>
> sa-update; retVal=$?

Nope, maar dit wel (denk beter als de eerdere):
if sa-update ; then retVal=0 ; else retVal=${?} ; fi

Cecil Westerhof

unread,
Nov 6, 2023, 10:44:05 AM11/6/23
to
Bedankt voor de heldere uitleg.

Was de 'oplossing' op het internet tegengekomen, maar het was dus geen
oplossing.


> Ik snap eigenlijk niet helemaal waarom je de accolades om de ? heen zet.
> Het mag, maar het lijkt mij hier overbodig en ietwat verwarrend.

Doe ik al heel lang omdat i.i.g. vroeger het zo was dat als je
gebruikte:
echo $pietjePuk

en de variabele pietjePuk niet bestond, maar pietje wel, dat je dan de
waarde kreeg in pietje met Puk erachter i.p.v. een fout, of lege string.

Dat is trouwens niet meer zo zie ik.

De ongekruisigde

unread,
Nov 6, 2023, 10:47:40 AM11/6/23
to
On 2023-11-06, Oscar <jornws...@xs4all.nl> wrote:
Dan doet het dus wel iets! Namelijk het op 0 zetten van de
resultaat code in ${?} wat niet 'null' genoemd kan worden. Een
wazige feature, dat :


>
> Het effect is hetzelfde. Cecil had dus ook 'sa-update || true' kunnen
> schrijven. Ik vind zelfs dat dat minder cryptisch is, dus beter.

ik ook


> Maar dan nog. Zelfs al zou enige variant /bin/true aanroepen, dan nog
> was dat niet het antwoord op de vraag waarom de resultaten verschillen.

als je die deling door 0 even buiten beschouwing laat dan heb heb
je nog steeds een vraag met twee mogelijkheden in de resultaten,
waarop ik antwoord heb gegeven (hoewel niet geheel kloppend, blijkt)


> Het enige juiste antwoord heb ik daarnet gegeven. Het verschil komt
> doordat bash zelf al een fout geeft op het evalueren van $((1/0))
> voordat de regel uitgevoerd kan worden.

dat is een heel ander verhaal waar ik niet eens op ben ingegaan

> Daar verandert geen 'which /bin/true' iets aan.

dat heb ik ook niet geschreven


>>Niet het pad naar true maar het feit dat je uit het bestaan van
>>dat pad kan afleiden true geen shell built-in is maar een extern
>>commando dat een resultaat code in ${?} zet. Enigszins cryptisch
>>misschien maar komaan zeg, welk niveau heeft men hier (*)?
>
> Het is dus niet eens een extern commando. En de hint leidt af van het
> werkelijke probleem. Ook al vervang je alle dubbele punten door
> /bin/true, dan nog krijg je het merkwaardige verschil tussen beide
> varianten.

ik had die : nog nooit gebruikt dus enige onbekendheid daarmee
heb ik mijzelf ondertussen al vergeven


>
>>(*) uit jouw uitleg in een ander antwoord leid ik af dat jij in
>>deze wel weet waarover je 't hebt.

zie je wel ;-)

>
> Dank. :-)

Oscar

unread,
Nov 6, 2023, 10:53:29 AM11/6/23
to
In article <87ttpy6...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>Maar dit is misschien een betere oplossing (duidelijker):
> if sa-update ; then retVal=0 ; else retVal=${?} ; fi
>
>Eigenlijk heb ik een grondige hekel aan 1-regelige if statements, maar
>in dit specifieke geval ben ik bereid een uitzondering te maken.


# variatie 1:
# subproces met stdout naar retVal

retVal=$(sa-update > /dev/null 2>&1; echo $?)

# variatie 2:
# retVal initialiseren en bij een fout aanpassen

retVal=0
sa-update || retVal=$?

# variatie 3:
# sa-update in de achtergrond draaien en
# met wait de exitcode opvangen

sa-update & wait
retVal=$?


Allemaal niet heel mooi. En dat allemaal omdat je die errexit zo graag
wil gebruiken. Meestal doe je dat als je zelf geen error-handling wil
doen, maar ook niet wil dat je script na een onverwachte fout door
blijft denderen. Hier wil je dus wel error-handling doen en dan kom je
dus in de knoop.

Misschien moet je je afvragen of het niet verstandiger is om die externe
aanroepen te draaien in een sectie van het script waar 'errexit' uit staat.

Hoe gebruik je die retVal verder? Is daar nog wat om heen te bouwen met
een mooiere if-constructie? Het kan wel eens veel leesbaarder worden
eerlijk gezegd. Net zoals de hint om niet : maar true te gebruiken.

Oscar

unread,
Nov 6, 2023, 11:05:44 AM11/6/23
to
In article <uib1qq$h4ak$2...@dont-email.me>,
De ongekruisigde <verstotene@invalid> wrote:
>Dan doet het dus wel iets! Namelijk het op 0 zetten van de
>resultaat code in ${?} wat niet 'null' genoemd kan worden.

Officieel doet het niks! En dat heel succesvol, dus returned het geen
error maar success. True zet expliciet de exitwaarde op 'Success'.

Moraal van dit verhaal: Als je true wil hebben, vraag dan om true.

>ik had die : nog nooit gebruikt dus enige onbekendheid daarmee
>heb ik mijzelf ondertussen al vergeven

Ik gebruik hem wel eens een enkele keer als 'nop' statement. Zoals je in
python wel eens 'pass' gebruikt.

De laatste keer dat ik hem gebruikte was om in de .bash_history aan te
geven wat ik aan het doen was, wetende dat er een grote kans is dat een
ander later mee zou kijken in die history. Een # komt niet in de history,
maar dit wel:

: uitleg wat ik ga doen
complex commando
nogeen commando
: resultaat was - iets
vervolgens een commando met 'iets'
exit

In deze specifieke situatie was dat even heel handig...

Maar het gebruik als alternatief voor 'true' deed mijn wenkrbouwen ook
wel even wat spierpijn. Vooral omdat ik er in eerste instantie falikant
overheen las. Dus Cecil: please! ;-)

Cecil Westerhof

unread,
Nov 6, 2023, 11:14:05 AM11/6/23
to
jornws...@xs4all.nl (Oscar) writes:

> In article <uiag01$efja$1...@dont-email.me>,
> De ongekruisigde <verstotene@invalid> wrote:
>>On 2023-11-06, Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> Oeps, belangrijk onderdeel vergeten te noemen. 🥵
>>> Ik gebruik in (bijna al) mijn scripts:
>>> set -o errexit
>
> Oh, aha. Dan snap ik je probleem.
>
>
>>lees dan dit nog maar eens goed door:
>>
>>https://stackoverflow.com/questions/44080974/if-errexit-is-on-how-do-i-run-a-command-that-might-fail-and-get-its-exit-code
>
> Dit is zowaar een bruikbare tip van De ongekruisigde.
>
> Maar nou is mijn vraag: heb je retVal echt nodig, ook als het goed gaat?

Yep, want er komt een hele lap code na die er gebruik van maakt.


> Zou je het zelfs zonder retVal afkunnen met deze leesbaardere
> constructie:
>
> if sa-update
> then
> # doe wat nodig is als sa-update goed gaat
> else
> # doe de foutafhandeling
> fi
>
> Jouw eerdere 'sa-update && retVal=0 || retVal=$?' zou je ook zo kunnen
> schrijven:
>
> if sa-update
> then
> retVal=0
> else
> retVal=$?
> fi
>
> En dat is eigenlijk net zo'n rare work-around. En al helemaal als je 2
> keer 'retVal=$?' schijft, ook waar die altijd 0 zal zijn.

Ik heb er al van gemaakt:
if sa-update ; then retVal=0 ; else retVal=${?} ; fi

Oscar

unread,
Nov 6, 2023, 11:14:55 AM11/6/23
to
In article <87leba6...@munus.decebal.nl>,
Zoals je het nu beschrijft, is het nooit geweest. Eerder andersom: Als
je de tekst Puk achter $Pietje wil plakken, dan doe je ${Pietje}Puk.
Met die accolades geef je heel duidelijk aan wat de naam van je
variabele is. Maar veel meer doet het ook niet, zo uit mijn hoofd. Als
de waarde een spatie bevat (of andere gevaarlijke tekens) dan wordt het
niet veiliger door ${PietjePuk} te gebruiken.

Wel snap ik dat je het zou doen als goede gewoonte. Het kan nooit kwaad
om die accolades om een variabele heen te zetten. Maar in het geval van
'$?' hebben we het over een variabele die ALTIJD bestaat en NOOIT een
andere waarde dan een integer getal kan hebben. De accolades zijn dan
niet alleen overbodig, ze leiden de lezer ook af van het feit dat je $?
aan het gebruiken bent. Ik moest in ieder geval twee keer kijken.

Die $? is zo'n standaard idioom, daar moet je niet aanzitten.

Naar mijn bescheiden mening natuurlijk. Andere inzichten zijn welkom.

Oscar

unread,
Nov 6, 2023, 11:36:57 AM11/6/23
to
In article <87h6ly6...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>> Maar nou is mijn vraag: heb je retVal echt nodig, ook als het goed gaat?
>Yep, want er komt een hele lap code na die er gebruik van maakt.

En die code kan niet simpelweg tussen de 'else' en 'fi'? Of als je het
omkeert:

if ! sa-update
then
: doe de dingen die je doet als het fout ging
else
: doe iets met de resultaten van de update
fi
: ga verder met het script


Of een hele andere invalshoek:

errors=0

sa-update || : $((errors++))
nog-iets || : $((errors++))
iets-anders || : $((errors++))

echo Aantal fouten: ${errors}

Hier gebruik je de : om precies niks te doen met de argumenten. Bash zal
die argumenten wel evalueren, met een increment van ${errors} tot gevolg.

Wordt allemaal niet veel leesbaarder. Ik weet niet of dat een doel is?

>Ik heb er al van gemaakt:
> if sa-update ; then retVal=0 ; else retVal=${?} ; fi

Ah. Nee dus. ;-)

De reden waarom je het zelf ook al niet fijn vindt om te lezen is omdat
het inderdaad onlogische code is. Snap je dit nog als je over een paar
jaar iets moet aanpassen? Zal een collega of opvolger deze "overbodige"
construcite weg willen optimaliseren, met dramatische gevolgen?

Cecil Westerhof

unread,
Nov 6, 2023, 12:59:05 PM11/6/23
to
jornws...@xs4all.nl (Oscar) writes:

> In article <87h6ly6...@munus.decebal.nl>,
> Cecil Westerhof <Ce...@decebal.nl> wrote:
>>> Maar nou is mijn vraag: heb je retVal echt nodig, ook als het goed gaat?
>>Yep, want er komt een hele lap code na die er gebruik van maakt.
>
> En die code kan niet simpelweg tussen de 'else' en 'fi'? Of als je het
> omkeert:
>
> if ! sa-update
> then
> : doe de dingen die je doet als het fout ging
> else
> : doe iets met de resultaten van de update
> fi
> : ga verder met het script

Nope, een 'foutcode' wordt gebruikt om een status terug te geven. Aan
de hand van de status code (inclusief 0) moeten dingen worden gedaan.
Het zou eventueel wel kunnen, maar het maakt de leesbaarheid er niet
beter op.

> Wordt allemaal niet veel leesbaarder. Ik weet niet of dat een doel is?

Vind ik zelfs belangrijker dan performance.


>>Ik heb er al van gemaakt:
>> if sa-update ; then retVal=0 ; else retVal=${?} ; fi
>
> Ah. Nee dus. ;-)
>
> De reden waarom je het zelf ook al niet fijn vindt om te lezen is omdat
> het inderdaad onlogische code is. Snap je dit nog als je over een paar
> jaar iets moet aanpassen? Zal een collega of opvolger deze "overbodige"
> construcite weg willen optimaliseren, met dramatische gevolgen?

Het is in i.i.g. een stuk leesbaarder dan de originele variant.
En heb ook erboven gezet:
# Need the return value of sa-update

Oscar

unread,
Nov 7, 2023, 5:25:04 AM11/7/23
to
In article <87y1fa4...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>Nope, een 'foutcode' wordt gebruikt om een status terug te geven.

duh


>Aan de hand van de status code (inclusief 0) moeten dingen worden
>gedaan. Het zou eventueel wel kunnen, maar het maakt de leesbaarheid
>er niet beter op.

Ik vraag me af hoe leesbaar 'retVal' is als je de afhandeling pas heel
veel verderop in het script doet. Maar mogelijk gebruik je daar een
zinniger naam?

Mijn aanpak zou waarschijnlijk zoiets zijn in een groter script:

# initialisatie
do_install_updates=yes

# [...]

# download updates
if ! sa-update; then
log_error "sa-update failed with exit code $?"
do_install_updates=no
fi

# [...]

# optionele extra tests
if ! check_disk_space $SIZE_NEEDED
log_error "Insufficient disk space; not installing updates"
do_install_updates=no
fi

# [...]

# install time!
if [ $do_install_updates == yes ]; then
install_updates
fi

Maar nu doe ik heel veel aannames over de flow in je script. ;-)


>Het is in i.i.g. een stuk leesbaarder dan de originele variant.
>En heb ook erboven gezet:
> # Need the return value of sa-update

Deze comment heeft ook een 100% match met:

sa-update
retVal=$?

Suggestie:

# Need to catch errors from sa-update because of -o errexit

Dat zou mij in ieder geval in het handboek doen kijken als ik niet weet
wat '-e' of '-o errexit' precies doet. Ook als de 'set -o errexit' meer
dan een schermvol van de code geleden is, dan kan is dit een nuttige
reminder.

Maar we dwalen af. Je vraag is beantwoord. Het was geen request for
comments op je coding style... ;-)

Cecil Westerhof

unread,
Nov 7, 2023, 9:28:05 AM11/7/23
to
jornws...@xs4all.nl (Oscar) writes:

> Ik vraag me af hoe leesbaar 'retVal' is als je de afhandeling pas heel
> veel verderop in het script doet. Maar mogelijk gebruik je daar een
> zinniger naam?

Naam is zeker niet de beste. (Code van tien jaar terug.) Maar hij
wordt ook meteen gebruikt:
# Need the return value of sa-update
if sa-update --debug 2>${_log_file} ; then retVal=0 ; else retVal=${?} ; fi
case ${retVal} in
0)
echo "Updated SpamAssassin rules"
systemctl restart spamd
;;
1)
echo "There where no updates for SpamAssassin rules"
;;
2)
.
.
.


>>Het is in i.i.g. een stuk leesbaarder dan de originele variant.
>>En heb ook erboven gezet:
>> # Need the return value of sa-update
>
> Deze comment heeft ook een 100% match met:
>
> sa-update
> retVal=$?
>
> Suggestie:
>
> # Need to catch errors from sa-update because of -o errexit
>
> Dat zou mij in ieder geval in het handboek doen kijken als ik niet weet
> wat '-e' of '-o errexit' precies doet. Ook als de 'set -o errexit' meer
> dan een schermvol van de code geleden is, dan kan is dit een nuttige
> reminder.

Dat is wel een goede: nu gaat het teveel van mij uit. Kans is niet
groot dat anderen deze code gaan lezen, maar je weet het maar nooit.
En het voorkomt dat ik hetzelfde doe bij andere code die wel door
anderen wordt gebruikt.


> Maar we dwalen af. Je vraag is beantwoord. Het was geen request for
> comments op je coding style... ;-)

Och, ik vind het nooit erg om dingen beter te leren doen. :-D


Nog een kleine aanvulling.
Er stond al jaren:
set +o errexit
sa-update --debug 2>${_log_file}
retVal=${?}
set -o errexit

Maar dat vond ik om meerdere reden niet mooi. Mijn grootste probleem
ermee was dat er wordt aangenomen dat errexit aanstaat. En dat zal in
dit programma ook zo zijn, maar ik kan me voorstellen dat het niet in
alle scripts zo zal zijn.
Vandaar dat ik eindelijk de stoute schoenen heb aangetrokken. ;-P

Oscar

unread,
Nov 7, 2023, 12:36:56 PM11/7/23
to
In article <87msvp3...@munus.decebal.nl>,
Cecil Westerhof <Ce...@decebal.nl> wrote:
>jornws...@xs4all.nl (Oscar) writes:
>
>> Ik vraag me af hoe leesbaar 'retVal' is als je de afhandeling pas heel
>> veel verderop in het script doet. Maar mogelijk gebruik je daar een
>> zinniger naam?
>
>Naam is zeker niet de beste. (Code van tien jaar terug.) Maar hij
>wordt ook meteen gebruikt:
># Need the return value of sa-update
> if sa-update --debug 2>${_log_file} ; then retVal=0 ; else retVal=${?} ; fi
> case ${retVal} in
> 0)
> echo "Updated SpamAssassin rules"
> systemctl restart spamd
> ;;
> 1)
> echo "There where no updates for SpamAssassin rules"
> ;;
> 2)
> .
> .
> .

Zou dit werken?

if sa-update --debug 2> ${_log_file}
then
echo "Updated SpamAssassin rules"
systemctl restart spamd
sa_result=0
else
sa_result=$?
case ${sa_result} in
0)
echo "Hoe zijn we hier terecht gekomen?"
exit 42
;;
1)
echo "There where no updates for...."
;;
.
.
.
esac
fi

Je ziet hier ook een persoonlijke voorkeur van mij om de 'then' op de
volgende regel te schrijven ipv '; then' aan het einde van de regel.


>Nog een kleine aanvulling.
>Er stond al jaren:
> set +o errexit
> sa-update --debug 2>${_log_file}
> retVal=${?}
> set -o errexit
>
>Maar dat vond ik om meerdere reden niet mooi. Mijn grootste probleem
>ermee was dat er wordt aangenomen dat errexit aanstaat. En dat zal in
>dit programma ook zo zijn, maar ik kan me voorstellen dat het niet in
>alle scripts zo zal zijn.

Je zou het in een subshell kunnen stoppen:

set -o errexit # of niet
.
.
.
(
set +o errexit
sa-udpate --debug 2> ${_log_file}
retVal=$?
)
.
.
.

Maar het grote nadeel is hier dat je retVal buiten de subshell weer
kwijt bent. Daar heb je dus niks aan als je er later wat mee wil.

En oh ja, de subshell heeft ook een exitcode. Als die niet 0 is, zal je
parent shell alsnog de errexit triggeren. Waardeloos advies dus. ;-)
0 new messages