Как проверить, успешно ли выполнена команда?

235

Есть ли способ проверить, есть ли ошибка при выполнении команды?

Пример :

test1=`sed -i "/:@/c connection.url=jdbc:oracle:thin:@$ip:1521:$dataBase" $search`
valid $test1

function valid () {
  if $test -eq 1; then
    echo "OK"
    else echo "ERROR" 
  fi
}

Я уже пытался сделать это, но кажется, что это не работает. Я не как это сделать.

moata_u
источник
9
Предпочитайте $ (foo) над обратными пометками `foo` , потому что вы можете вложить его, и его легче отличить от апострофов.
пользователь неизвестен
1
Кстати, вам нужно определить функцию ( valid), прежде чем вызывать ее.
августа

Ответы:

345

Возвращаемое значение сохраняется в $?. 0 указывает на успех, другие указывают на ошибку.

some_command
if [ $? -eq 0 ]; then
    echo OK
else
    echo FAIL
fi

Как и любое другое текстовое значение, вы можете сохранить его в переменной для последующего сравнения:

some_command
retval=$?
do_something $retval
if [ $retval -ne 0 ]; then
    echo "Return code was not zero but $retval"
fi

Для возможных операторов сравнения, см man test.

Lekensteyn
источник
Это хорошо ... я могу держать ошибку вывода ?? !! , потому что в этом случае у меня есть 2 ошибки: ошибка команды «текст» ex, файл не найден, и моя ошибка «текст», которая в этом случае, например, не удалась
moata_u
@moata_u: вы можете сохранить значение в переменной, как показано в моем ответе.
Лекенштейн
@moata_u: Вам нужно поставить ;перед elseи fi: `if ...; тогда ...; еще ...; фи
Лекенштейн
4
Это бесполезное использованиеtest .
Дэвид Фёрстер
1
@Blauhirn [ $? ](или, что то же самое, test $?) не работает, поскольку $?вычисляет число (0, 1 и т. Д.), Которое не равно нулю. См. Документы дляtest : «Если EXPRESSION опущено,« test »возвращает false. Если EXPRESSION является единственным аргументом,« test »возвращает false, если аргумент равен нулю и true в противном случае».
Лекенштейн
87

Если вам нужно только знать, была ли команда выполнена успешно или нет, не беспокойтесь о тестировании $?, просто протестируйте команду напрямую. Например:

if some_command; then
    printf 'some_command succeeded\n'
else
    printf 'some_command failed\n'
fi

И присвоение вывода переменной не меняет возвращаемого значения (ну, если, конечно, он не ведет себя иначе, когда stdout не является терминалом).

if output=$(some_command); then
    printf 'some_command succeded, the output was «%s»\n' "$output"
fi

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals объясняет ifболее подробно.

geirha
источник
Что, если вы хотите сделать что-то кроме ветвления, например, сохранить логическое значение того, произошел ли сбой или нет в .ini? Тогда ваша выходная переменная не делает этого, но $?делает, так что вы ошибаетесь, говоря, что тестирование команды напрямую лучше.
Тимоти Свон
Присвоение выходных данных переменной может изменить возвращаемое значение, когда используется localкоманда, т. local foo=$(false); echo $?;Е. Производится 0на выходе. Но localотносится только к функциям bash.
Cromax
26
command && echo OK || echo Failed
Авраам Санчес
источник
Если commandна экране появляется ошибка, как ее скрыть?
Сигур
Если вы commandзаписываете ошибки в stderr, вы можете использовать форму command 2> /dev/null && echo OK || echo Failed. В 2> /dev/nullпереадресовывает вывод на стандартный вывод /dev/null. Однако некоторые утилиты будут записывать ошибки в стандартный вывод (даже если это плохая практика). В этом случае вы можете опустить 2 из перенаправления, но вы потеряете любой вывод команды. Этот метод проверки успешности хорош для простой троичной логики, но для более сложного поведения лучше всего проверить $?успешность команды или использовать ifблочный метод, описанный в ответе @ geirha.
Величайший Бендер
17

$? должен содержать статус выхода предыдущей команды, который должен быть нулевым для отсутствия ошибок.

Итак, что-то вроде;

cd /nonexistant
if [ $? -ne 0 ]
then
    echo failed
else
    echo success!
fi

в большинстве случаев проще использовать конструкцию && для объединения команд, которые должны зависеть друг от друга. Так cd /nonexistant && echo success!что не повторило бы успех, потому что команда прерывается до &&. Следствием этого является ||, где cd /nonexistant || echo fail будет эхо-сбой, потому что CD-сбой. (это становится полезным, если вы используете что-то вроде || exit, что завершит работу сценария, если предыдущая команда не удалась.)

Shaun
источник
Это хорошо ... я могу держать ошибку вывода ?? !! , потому что в этом случае у меня есть 2 ошибки: ошибка команды «text» ex, файл не найден, и моя ошибка «text», которая в этом случае, например, не удалась
moata_u
@moata_u, см. mywiki.wooledge.org/BashFAQ/002
гейра
5
command && echo $? || echo $?
modrobert
источник
Вы имеете в виду command; echo $??
Хавьер Баззи
Нет, моя строка правильная, она выдает фактический код результата в виде числа независимо от того, успешен он или нет.
модроберт
1
Хорошо, пожалуйста, объясните мне эти различия: true && echo $? || echo $?/ true; echo $?и false && echo $? || echo $?/ false; echo $?- вы обнаружите, что они делают одно и то же: D
Хавьер Буззи
Да, тот же результат, но без условия. Первоначальный вопрос был «Как проверить, была ли команда выполнена?», Это было основано на предыдущих ответах. Я думаю, что лучшим примером будет:command && echo "success: $?" || echo "fail: $?"
модроберт
5

Следует отметить, что if...then...fiи &&/ ||тип подхода имеет дело с состоянием выхода, возвращаемым командой, которую мы хотим проверить (0 в случае успеха); однако некоторые команды не возвращают ненулевой статус выхода, если команда не выполнена или не может обработать ввод. Это означает, что обычный ifи &&/ ||подходы не будут работать для этих конкретных команд.

Например, в Linux GNU по- fileпрежнему завершает работу с 0, если он получил несуществующий файл в качестве аргумента и findне может найти указанный файл пользователем.

$ find . -name "not_existing_file"                                          
$ echo $?
0
$ file ./not_existing_file                                                  
./not_existing_file: cannot open `./not_existing_file' (No such file or directory)
$ echo $?
0

В таких случаях одним из возможных способов справиться с ситуацией является чтение stderr/ stdinсообщения, например, те, которые были возвращены fileкомандой, или анализ выходных данных команды, как в find. Для этого caseможно использовать заявление.

$ file ./doesntexist  | while IFS= read -r output; do                                                                                                                  
> case "$output" in 
> *"No such file or directory"*) printf "%s\n" "This will show up if failed";;
> *) printf "%s\n" "This will show up if succeeded" ;;
> esac
> done
This will show up if failed

$ find . -name "doesn'texist" | if ! read IFS= out; then echo "File not found"; fi                                                                                     
File not found

(Это репост моего собственного ответа на связанный вопрос на unix.stackexchange.com )

Сергей Колодяжный
источник
1

Как уже упоминалось во многих других ответов, простой тест $?будет делать, как это

if [ $? -eq 0 ]; then something; fi

Если вы хотите проверить , если команда не удалось , вы можете использовать более короткую версию в bash(но , возможно , избыточна) следующим образом :

if (($?)); then something; fi

Это работает с использованием (( ))арифметического режима, поэтому, если команда вернулась success, то есть $? = 0тогда тест оценивает, к ((0))каким тестам как false, иначе он вернется true.

Чтобы проверить успех , вы можете использовать:

if ! (($?)); then something; fi

но это уже не намного короче, чем первый пример.

afuna
источник
1
конструктивная критика?
Афуна
0

Для проверки ошибок ваших команд:

execute [INVOKING-FUNCTION] [COMMAND]

execute () {
    error=$($2 2>&1 >/dev/null)

    if [ $? -ne 0 ]; then
        echo "$1: $error"
        exit 1
    fi
}

Вдохновленный в Бережливом производстве:

Альберто Сальвия Новелла
источник
-2

if [$ (команда)]; тогда эхо "преуспевает"; фи

amozejko
источник
3
trueудается, if [ $(true) ]; then echo "succeed"; fiно succeedне печатается. На самом деле это никогда не проверяет, если это commandудалось. Это следует использовать if commandкак в сообщении гейры . $( )это подстановка команды . [ ]это условное выражение . Отсутствие разбиения по словам и расширения имени файла , это в основном проверяет, были ли commandвыходные данные.
Элия ​​Каган