Considere los comandos
eval false || echo ok
echo also ok
Normalmente, esperaríamos que esto ejecutara la false
utilidad y, dado que el estado de salida es distinto de cero, luego ejecutaría echo ok
y echo also ok
.
En todos los shells tipo POSIX que uso ( ksh93
,,, OpenBSD y ), esto es lo que sucede, pero las cosas se ponen interesantes si habilitamos .zsh
bash
dash
ksh
yash
set -e
Si set -e
está vigente, OpenBSD sh
y ksh
shells (ambos derivados de pdksh
) finalizarán el script al ejecutar eval
. Ningún otro caparazón hace eso.
POSIX diceque un error en una utilidad especial incorporada (como eval
) debería provocar la finalización del shell no interactivo. No estoy del todo seguro de si la ejecución false
constituye "un error" (si lo fuera, sería independiente de set -e
estar activo).
La forma de solucionar esto parece ser colocarlo eval
en un subshell,
( eval false ) || echo ok
echo also ok
La pregunta es si se espera que tenga que hacer eso en un script de shell POSIX correcto o si se trata de un error en el shell de OpenBSD. Además, ¿qué se entiende por "error" en el texto POSIX vinculado anteriormente?
Un poco de información adicional: los shells de OpenBSD ejecutarán echo ok
tanto con como sin set -e
en el comando
eval ! true || echo ok
Mi código original parecía
set -e
if eval "$string"; then
echo ok
else
echo not ok
fi
Cuál deberíanosalida not ok
con string=false
el uso de shells de OpenBSD (terminaría), y no estaba seguro de que fuera por diseño, por error o por malentendido, o algo más.
Respuesta1
El hecho de que ningún otro shell necesite dicha solución es un fuerte indicio de que se trata de un error en OpenBSD ksh. De hecho, ksh93 no muestra ese problema.
Que haya un ||
en la línea de comando debe evitar la salida del shell provocada por un código de retorno de 1 en el lado izquierdo del mismo.
El error de unespecialincorporado provocará la salida de un shell no interactivosegún POSIXpero eso no siempre es cierto. Intentar continue
salir de un bucle es un error y continue
es una función incorporada. Pero la mayoría de los shells no salen en:
continue 3
Un incorporado que emite un error claro pero no sale.
Entonces, la salida false
es generada por la set -e
condición, no por la característica incorporada del comando ( eval
en este caso).
Las condiciones exactas sobre las cuales set -e
se saldrá son bastante más confusas en POSIX.
Respuesta2
[lo siento si esta no es una respuesta real, la actualizaré cuando llegue el momento]
Eché un vistazo al código fuente y mis conclusiones son:
1) Es un error/limitación, no hay nada filosófico detrás de esto.
mksh
2) La "solución" de la bifurcación portátil de ksh ( ) de OpenBSD esmuypobre, sólo empeora las cosas, sin realmente arreglarlas:
Nuevo error, diferente de todos los demás shells:
mksh -ec 'eval "false; echo yup"'
yup
bash -ec 'eval "false; echo yup"'
(nothing)
Todavía no está realmente solucionado:
mksh -ec 'eval "set -e; false" || echo yup'
(nothing)
bash -ec 'eval "set -e; false" || echo yup'
yup
Puede reemplazar bash
lo anterior con dash
, zsh
, yash
, ksh93
etc.