Comportamento di "eval" sotto "set -e" nell'espressione condizionale


9

Considera i comandi

eval false || echo ok
echo also ok

Normalmente, ci aspettiamo che questo esegua l' falseutilità e, poiché lo stato di uscita è diverso da zero, quindi eseguirà echo oke echo also ok.

In tutto il POSIX come gusci che uso ( ksh93, zsh, bash, dash, OpenBSD ksh, e yash), questo è ciò che accade, ma le cose si fanno interessanti, se permettiamo set -e.

Se set -eè attivo, OpenBSD she kshshell (entrambi derivati ​​da pdksh) termineranno lo script durante l'esecuzione di eval. Nessun altra shell lo fa.

POSIX afferma che un errore in un'utilità integrata speciale (come eval) dovrebbe causare la chiusura della shell non interattiva. Non sono del tutto sicuro se l'esecuzione falsecostituisca "un errore" (se lo fosse, sarebbe indipendente set -edall'essere attivo).

Il modo per ovviare a questo sembra essere quello di mettere il evalsub in una shell secondaria,

( eval false ) || echo ok
echo also ok

La domanda è se mi aspetto che debba farlo in uno script shell corretto da POSIX o se si tratta di un bug nella shell di OpenBSD? Inoltre, cosa si intende per "errore" nel testo POSIX collegato sopra?


Ulteriori informazioni: le shell OpenBSD eseguiranno echo okentrambe le operazioni con e senza set -e nel comando

eval ! true || echo ok

Il mio codice originale sembrava

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi

che non sarebbe uscito not okcon l' string=falseuso delle shell OpenBSD (sarebbe terminato), e non ero sicuro che fosse progettato, per errore o incomprensione, o qualcos'altro.


eval falsegenera uno stato diverso da zero, quindi mi aspetterei set -edi terminare lo script a quel punto. Nel caso di ! set -enon si applica poiché la !dichiarazione verifica esplicitamente lo stato di uscita.
fcbsd,

@fcbsd Ti aspetti eval falsedi terminare lo script anche se fa parte di un elenco AND-OR o di un'istruzione condizionale? Non lo farei.
Kusalananda

Non sono sicuro che set -esia impostato se si tratta del comportamento corretto ... Sono d'accordo sul fatto che abbia senso non terminare in una dichiarazione condizionale.
fcbsd,

avendo giocato ancora un po ', con sh su CentOS 7 - Direi che è un comportamento previsto per ksh / sh di OpenBSD quando lo uso, set -equindi `()` è la risposta.
fcbsd,

Risposte:


4

Il fatto che nessun altra shell abbia bisogno di una soluzione simile è una forte indicazione che si tratta di un bug in OpenBSD ksh. In effetti, ksh93 non mostra questo problema.

Che ci sia un ||nella riga di comando deve evitare l'uscita della shell causata da un codice di ritorno di 1 sul lato sinistro di esso.

L'errore di un built-in speciale deve causare l'uscita di una shell non interattiva secondo POSIX ma ciò non è sempre vero. Provare a continueuscire da un ciclo è un errore ed continueè incorporato. Ma la maggior parte delle shell non esce:

continue 3

Un built-in che genera un errore chiaro ma non si chiude.

Pertanto, l'uscita attivata falseviene generata dalla set -econdizione non dalla caratteristica incorporata del comando ( evalin questo caso).

Le condizioni esatte su cui set -edeve uscire sono molto più confuse in POSIX.


Questo fa eco alla risposta che ho ricevuto dalla mailing list di OpenBSD, ma con più parole, grazie! Risolverò una corretta segnalazione di bug e, se non succede nulla, guarderò io stesso il codice sorgente.
Kusalananda

4

[scusate se questa non è una vera risposta, la aggiornerò quando arrivo ad essa]

Ho dato un'occhiata al codice sorgente e le mie conclusioni sono:

1) È un bug / limitazione, niente di filosofico dietro di esso.

2) La "correzione" per esso dal fork portatile del ksh ( mksh) di OpenBSD è molto scarsa, solo peggiorando le cose, senza davvero risolverlo:

Nuovo bug, diverso da tutti gli altri gusci:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

Non ancora risolto:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

È possibile sostituire bashsopra con dash, zsh, yash, ksh93, etc.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.