Capture el código de salida del comando de salida

10

Tengo esto en un script bash:

exit 3;

exit_code="$?"

if [[ "$exit_code" != "0" ]]; then
    echo -e "${r2g_magenta}Your r2g process is exiting with code $exit_code.${r2g_no_color}";
    exit "$exit_code";
fi

Parece que saldrá justo después del comando de salida, lo cual tiene sentido. Me preguntaba si hay algún comando simple que pueda proporcionar un código de salida sin salir de inmediato.

Iba a adivinar:

exec exit 3

pero da un mensaje de error: exec: exit: not found. ¿Que puedo hacer? :)

G-Man dice 'restablecer a Mónica'
fuente
1
Sí, exec exit 3no es bueno, obtengo"exec: exit: not found"
77
No entiendo la pregunta. ¿Por qué no establecer exit_code=3y eliminar la exit 3línea por completo?
wjandrea
@wjandrea es más una pregunta conceptual que práctica
2
Todavía no tiene sentido para mí. ¿Por qué habría un código de salida si en realidad no sales?
Barmar
1
@Barmar cada proceso tiene un código de salida. La mayoría de las personas que intentan responder la pregunta están interpretando que la pregunta significa "¿con qué puedo reemplazar la 'salida 3' en el script para que establezca la $?variable pero no salga de este script"?
icarus

Respuestas:

32

Si tiene un script que ejecuta algún programa y mira el estado de salida del programa (con  $?), y desea probar ese script haciendo algo que haga $?que se establezca en algún valor conocido (por ejemplo,  3), simplemente haga

(exit 3)

Los paréntesis crean un sub-shell. Luego, el exitcomando hace que ese sub-shell salga con el estado de salida especificado.

G-Man dice 'restablecer a Mónica'
fuente
Además, para fines de depuración, sería igual de simple configurarlo exit_code="3"para pruebas
Centimane,
1
Sí, wjandrea lo señaló ayer.
G-Man dice 'Restablecer a Mónica'
12

exites un bash incorporado, por lo que no puedes exechacerlo. Por manual de bash :

El estado de salida de Bash es el estado de salida del último comando ejecutado en el script. Si no se ejecutan comandos, el estado de salida es 0.

Al unir todo esto, diría que su única opción es almacenar el estado de salida deseado en una variable y luego, exit $MY_EXIT_STATUScuando sea apropiado.

solarshado
fuente
hmmm, ¿qué opinas sobre la idea de @ G-man?
2
Tal vez no entendí lo que intentas lograr. Si solo está tratando de configurar $?(aunque no estoy realmente seguro de por qué lo haría), eso parece una respuesta sólida. Si solo desea establecerlo en algún valor fallido, falsees otra opción.
solarshado
10

Puede escribir una función que devuelva el estado dado como argumento, o 255si no se da ninguno. (Lo llamo porque ret"devuelve" su valor).

ret() { return "${1:-255}"; }

y use reten lugar de su llamada a exit. Esto evita la ineficiencia de crear el sub-shell en la respuesta actualmente aceptada.

Algunas medidas

time bash -c 'for i in {1..10000} ; do (exit 3) ; done ; echo $?'

en mi máquina tarda unos 3,5 segundos.

 time bash -c 'ret(){ return $1 ; } ; for i in {1..10000} ; do ret 3 ; done ; echo $?'

en mi máquina toma aproximadamente 0.051 segundos, 70 veces más rápido. Poner el manejo predeterminado todavía lo deja 60 veces más rápido. Obviamente, el bucle tiene algo de sobrecarga. Si cambio el cuerpo del bucle a solo ser :o trueel tiempo se reduce a la mitad a 0.025, un bucle completamente vacío es una sintaxis no válida. Agregar ;:al bucle muestra que este comando mínimo tarda 0.007 segundos, por lo que la sobrecarga del bucle es de aproximadamente 0.018. Restar esta sobrecarga de las dos pruebas muestra que la retsolución es más de 100 veces más rápida.

Obviamente esta es una medida sintética, pero las cosas se suman. Si hace que todo sea 100 veces más lento de lo necesario, terminará con sistemas lentos. 0.0

Ícaro
fuente
2
@iBug El espacio extra no es necesario.
icarus
Buen punto sobre la ineficiencia de la creación de la sub-shell. He leído que algunos shells pueden ser lo suficientemente inteligentes como para optimizar el fork en casos como este, pero ese bash no es uno de ellos.
G-Man dice 'Restablecer a Monica' el
3

Acerca de exec exit 3... intentaría ejecutar un comando externo llamado exit, pero no hay ninguno, por lo que obtiene el error. Tiene que ser un comando externo en lugar de uno integrado en el shell, ya que exec reemplaza el shell por completo. Lo que también significa que incluso si tuviera un comando externo llamado exit, exec exit 3no volvería a continuar su script de shell, ya que el shell ya no estaría allí .

ilkkachu
fuente
1
Supongo que podrías hacerlo exec bash -c "exit 3", pero por el momento no se me ocurre ninguna razón para hacerlo en lugar de solo exit 3.
David Z
1
@DavidZ, en cualquier caso, exec'ing' o exit'' solo detendrá el script, que no parecía lo que la pregunta quería.
ilkkachu
3

Puedes hacer esto con Awk:

awk 'BEGIN{exit 9}'

O sed:

sed Q9 /proc/stat
Steven Penny
fuente
... o con una concha:sh -c 'exit 9'
ilkkachu
1
@ilkkachu si vas a hacer eso, también podrías hacerlo (exit 9)en la respuesta aceptada
Steven Penny