Подтвердить что ты не робот

Получить код выхода для команды в bash/ksh

Я хочу написать такой код:

command="some command"

safeRunCommand $command

safeRunCommand() {
   cmnd=$1

   $($cmnd)

   if [ $? != 0 ]; then
      printf "Error when executing command: '$command'"
      exit $ERROR_CODE
   fi
}

Но этот код работает не так, как я хочу. Где я ошибся?

4b9b3361

Ответ 1

Ниже приведен фиксированный код:

#!/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"

Теперь, если вы посмотрите на этот код, несколько вещей, которые я изменил, следующие:

  • использование typeset не является необходимым, но является хорошей практикой. Он делает cmnd и ret_code локальным для safeRunCommand
  • Использование ret_code не обязательно, но хорошая практика для хранения кода возврата в некоторой переменной (и сохранить его как можно скорее), чтобы вы могли использовать ее позже, как я сделал в printf "Error : [%d] when executing command: '$command'" $ret_code
  • передайте команду с кавычками, окружающими команду, как safeRunCommand "$command". Если вы не сделаете, то cmnd получит только значение ls, а не ls -l. И еще важнее, если ваша команда содержит каналы.
  • вы можете использовать typeset cmnd="$*" вместо typeset cmnd="$1", если хотите сохранить пробелы. Вы можете попробовать оба в зависимости от того, насколько сложным является ваш аргумент команды.
  • eval используется для оценки того, что команда, содержащая трубы, может работать нормально

ПРИМЕЧАНИЕ. Помните, что некоторые команды дают 1 в качестве кода возврата, даже если нет ошибки, например grep. Если grep найдет что-то, он вернет 0 else 1.

Я тестировал с KSH/ BASH. И все получилось отлично. Дайте мне знать, если у вас возникли проблемы с этим.

Ответ 2

Try

safeRunCommand() {
   "[email protected]"

   if [ $? != 0 ]; then
      printf "Error when executing command: '$1'"
      exit $ERROR_CODE
   fi
}

Ответ 3

Он должен быть $cmd вместо $($cmd). Хорошо работает с этим на моей коробке.

Изменить: Ваш script работает только для команд с одним словом, например ls. Это не будет работать для "ls cpp". Для этого замените cmd="$1"; $cmd на "[email protected]". И не запускайте script как command="some cmd"; safeRun command, запустите его как safeRun some cmd.

Кроме того, когда вам нужно отлаживать ваши сценарии bash, выполните с помощью флага -x. [bash -x s.sh].

Ответ 4

В вашем script есть несколько ошибок.

Функции (подпрограммы) должны быть объявлены перед попыткой вызвать их. Вероятно, вы хотите возвратить(), но не выйти() из своей подпрограммы, чтобы позволить вызывающему блоку проверить успех или сбой конкретной команды. В остальном вы не захватываете "ERROR_CODE", поэтому всегда ноль (undefined).

Хорошая практика - объединить ваши переменные ссылки с фигурными фигурными скобками. Ваш код может выглядеть так:

#!/bin/sh
command="/bin/date -u"          #...Example Only

safeRunCommand() {
   cmnd="[email protected]"                    #...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

Ответ 5

Обычной идеей было бы запустить команду, а затем использовать $? для получения кода выхода. Однако несколько раз у вас есть несколько случаев, когда вам нужно получить код выхода. Например, вам может потребоваться скрыть его вывод, но все же вернуть код выхода или распечатать код выхода и выход.

ec() { [[ "$1" == "-h" ]] && { shift && eval $* > /dev/null 2>&1; ec=$?; echo $ec; } || eval $*; ec=$?; }

Это даст вам возможность подавить вывод команды, для которой требуется код выхода. Когда выход подавляется для команды, код выхода будет возвращен функцией.

Мне лично нравится помещать эту функцию в мой .bashrc файл

Ниже я продемонстрирую несколько способов, которыми вы можете использовать это:


# 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

Решение вашего кода с помощью этой функции

#!/bin/bash
if [[ "$(ec -h 'ls -l | grep p')" != "0" ]]; then
    echo "Error when executing command: 'grep p' [$ec]"
    exit $ec;
fi

Следует также отметить, что код выхода, который вы увидите, будет выполняться при выполнении команды grep, так как это последняя выполняемая команда. Не ls.