Obtener código de salida para el comando en bash / ksh
Quiero escribir código como este:
command="some command"
safeRunCommand $command
safeRunCommand() {
cmnd=$1
$($cmnd)
if [ $? != 0 ]; then
printf "Error when executing command: '$command'"
exit $ERROR_CODE
fi
}
Pero este código no funciona de la manera que quiero. ¿Dónde cometí un error?
5 answers
A continuación se muestra el código fijo:
#!/bin/ksh
safeRunCommand() {
typeset cmnd="$*"
typeset ret_code
echo cmnd=$cmnd
eval $cmnd
ret_code=$?
if [ $ret_code != 0 ]; then
printf "Error : [%d] when executing command: '$cmnd'" $ret_code
exit $ret_code
fi
}
command="ls -l | grep p"
safeRunCommand "$command"
Ahora, si miras este código, pocas cosas que cambié son: {[16]]}
- el uso de
typeset
no es necesario, sino una buena práctica. Hacecmnd
yret_code
local asafeRunCommand
- el uso de
ret_code
no es necesario, pero una buena práctica para almacenar código de retorno en alguna variable (y almacenarlo lo antes posible) para que pueda usarlo más tarde como lo hice enprintf "Error : [%d] when executing command: '$command'" $ret_code
- pase el comando con comillas rodeando el comando como
safeRunCommand "$command"
. Si usted no entoncescmnd
obtendrá solo el valorls
y nols -l
. Y es aún más importante si su comando contiene tuberías. - puede usar
typeset cmnd="$*"
en lugar detypeset cmnd="$1"
si desea mantener los espacios. Puede probar con ambos dependiendo de lo complejo que sea su argumento de comando. - eval se utiliza para evaluar para que el comando que contiene tuberías pueda funcionar bien
NOTA: Recuerde que algunos comandos dan 1 como código de retorno a pesar de que no hay error como grep
. Si grep
encontró algo lo hará devuelve 0 más 1.
Había probado con KSH/BASH. Y funcionó bien. Avísame si tienes problemas con esto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-24 03:08:46
Intenta
safeRunCommand() {
"$@"
if [ $? != 0 ]; then
printf "Error when executing command: '$1'"
exit $ERROR_CODE
fi
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-21 12:53:07
Debe ser $cmd
en lugar de $($cmd)
. Funciona bien con eso en mi caja.
Edit: Su script solo funciona para comandos de una palabra, como ls. No funcionará para "ls cpp". Para que esto funcione, reemplace cmd="$1"; $cmd
por "$@"
. Y, no ejecute su script como command="some cmd"; safeRun command
, ejecútelo como safeRun some cmd
.
También, cuando tengas que depurar tus scripts bash, ejecuta con la bandera '-x'. [bash-x s.sh].
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-22 05:26:50
Hay varias cosas mal con su script.
Las funciones (subrutinas) deben declararse antes de intentar llamarlas. Probablemente quieras devolver () pero no exit() de tu subrutina para permitir que el bloque de llamada pruebe el éxito o el fracaso de un comando en particular. Aparte de eso, no captura 'ERROR_CODE' por lo que siempre es cero (indefinido).
Es una buena práctica rodear sus referencias de variables con llaves, también. Tu código podría verse como:
#!/bin/sh
command="/bin/date -u" #...Example Only
safeRunCommand() {
cmnd="$@" #...insure whitespace passed and preserved
$cmnd
ERROR_CODE=$? #...so we have it for the command we want
if [ ${ERROR_CODE} != 0 ]; then
printf "Error when executing command: '${command}'\n"
exit ${ERROR_CODE} #...consider 'return()' here
fi
}
safeRunCommand $command
command="cp"
safeRunCommand $command
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-21 14:31:14
La idea normal sería ejecutar el comando y luego usar $?
para obtener el código de salida. Sin embargo, algunas veces tiene varios casos en los que necesita obtener el código de salida. Por ejemplo, es posible que deba ocultar su salida, pero aún así devolver el código de salida, o imprimir tanto el código de salida como la salida.
ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }
Esto le dará la opción de suprimir la salida del comando para el que desea el código de salida. Cuando la salida se suprime para el comando, el código de salida será directamente devuelto por la función.
Personalmente me gusta poner esta función en mi archivo .bashrc
A continuación te muestro algunas maneras en las que puedes usar esto:
# In this example, the output for the command will be
# normally displayed, and the exit code will be stored
# in the variable $ec.
$ ec echo test
test
$ echo $ec
0
# In this example, the exit code is output
# and the output of the command passed
# to the `ec` function is suppressed.
$ echo "Exit Code: $(ec -h echo test)"
Exit Code: 0
# In this example, the output of the command
# passed to the `ec` function is suppressed
# and the exit code is stored in `$ec`
$ ec -h echo test
$ echo $ec
0
Solución a su código usando esta función
#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
echo "Error when executing command: 'grep p' [$ec]"
exit $ec;
fi
También debe tener en cuenta que el código de salida que verá será para el comando
grep
que se está ejecutando, ya que es el último comando que se está ejecutando. No ells
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-11 18:55:01