Zachowanie „eval” pod „set -e” w wyrażeniu warunkowym


10

Rozważ polecenia

eval false || echo ok
echo also ok

Zwykle spodziewalibyśmy się, że uruchomi to falsenarzędzie, a ponieważ status wyjścia jest różny od zera, to wykonamy echo oki echo also ok.

We wszystkich POSIX-jak muszli używam ( ksh93, zsh, bash, dash, OpenBSD ksh, a yash), to jest to, co się dzieje, ale robi się ciekawie, jeśli pozwalają set -e.

Jeśli set -edziała, OpenBSD shi kshpowłoki (oba pochodzące z pdksh) zakończą skrypt podczas wykonywania eval. Żadna inna powłoka tego nie robi.

POSIX mówi, że błąd w specjalnym wbudowanym narzędziu (takim jak eval) powinien spowodować zakończenie nieinteraktywnej powłoki. Nie jestem do końca pewien, czy wykonanie falsejest „błędem” (gdyby tak było, byłoby niezależne od set -ebycia aktywnym).

Wydaje się, że sposobem obejścia tego jest umieszczenie evalsub-powłoki,

( eval false ) || echo ok
echo also ok

Pytanie brzmi, czy mam to zrobić w poprawnym skrypcie powłoki POSIX-owym, czy też jest to błąd w powłoce OpenBSD? Co również oznacza „błąd” w tekście POSIX połączonym z powyższym?


Dodatkowy bit informacji: Powłoki OpenBSD wykonają echo okoba polecenia z lub bez set -e polecenia

eval ! true || echo ok

Mój oryginalny kod wyglądał

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

które nie byłyby generowane not okprzy string=falseużyciu powłok OpenBSD (to by się zakończyło), i nie byłem pewien, czy to z założenia, przez pomyłkę, przez nieporozumienie, czy coś innego.


eval falsegeneruje niezerowy status, więc spodziewałbym set -esię, że w tym momencie zakończę skrypt. W przypadku ! set -enie ma zastosowania, ponieważ !oświadczenie wyraźnie sprawdza status wyjścia.
fcbsd,

@fcbsd Czy spodziewałbyś eval falsesię zakończyć skrypt, nawet jeśli jest on częścią listy AND-OR lub instrukcji warunkowej? Nie zrobiłbym tego.
Kusalananda

Nie jestem pewien, czy set -ejest ustawione, jeśli jest to prawidłowe zachowanie ... Zgadzam się, że sensowne jest, aby nie kończyć się instrukcją warunkową.
fcbsd

grałem jeszcze trochę, z sh na CentOS 7 - powiedziałbym, że jest to zamierzone zachowanie dla ksh / sh OpenBSD podczas używania, set -ewięc `()` jest odpowiedzią.
fcbsd,

Odpowiedzi:


4

To, że żadna inna powłoka nie potrzebuje takiego obejścia, jest silnym sygnałem, że jest to błąd w ksh OpenBSD. W rzeczywistości ksh93 nie pokazuje takiego problemu.

To, że ||w wierszu poleceń znajduje się znak, musi unikać wyjścia powłoki spowodowanego przez kod powrotu 1 po lewej stronie.

Błąd specjalnego wbudowanego spowoduje wyjście z nieinteraktywnej powłoki zgodnie z POSIX, ale nie zawsze tak jest. Próba continuewyjścia z pętli jest błędem i continuejest wbudowana. Ale większość pocisków nie wychodzi po:

continue 3

Wbudowany, który emituje wyraźny błąd, ale nie wychodzi.

Tak więc wyjście włączone falsejest generowane przez set -ewarunek, a nie przez wbudowaną charakterystykę polecenia ( evalw tym przypadku).

Dokładne warunki set -ewyjścia, są bardziej rozmyte w POSIX.


To odzwierciedla odpowiedź, że wyjąłem z listy mailingowej OpenBSD, ale z większą ilością słów, dziękuję! Ułożę odpowiedni raport o błędach, a jeśli nic się nie stanie, sam przyjrzę się kodowi źródłowemu.
Kusalananda

4

[przepraszam, jeśli to nie jest prawdziwa odpowiedź, zaktualizuję ją, kiedy do niej przejdę]

Rzuciłem okiem na kod źródłowy, a moje wnioski są następujące:

1) To błąd / ograniczenie, nic filozoficznego.

2) „Poprawka” z przenośnego rozwidlenia ksh ( mksh) OpenBSD jest bardzo słaba, tylko pogarsza, bez naprawiania:

Nowy błąd, inny niż wszystkie inne powłoki:

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

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

Wciąż nie naprawiony:

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

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

Można zastąpić bashpowyżej dash, zsh, yash, ksh93, itd.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.