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?

Author: javaPlease42, 2011-11-21

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. Hace cmnd y ret_code local a safeRunCommand
  • 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 en printf "Error : [%d] when executing command: '$command'" $ret_code
  • pase el comando con comillas rodeando el comando como safeRunCommand "$command". Si usted no entonces cmnd obtendrá solo el valor ls y no ls -l. Y es aún más importante si su comando contiene tuberías.
  • puede usar typeset cmnd="$*" en lugar de typeset 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.

 59
Author: havexz,
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
}
 5
Author: sehe,
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].

 2
Author: Priyank Bhatnagar,
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
 1
Author: JRFerguson,
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 el ls.

 0
Author: Nathan Fiscaletti,
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