Як перевірити, чи вдала команда?


234

Чи є спосіб перевірити, чи є помилка у виконанні команди?

Приклад:

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
}

Я вже намагався це зробити, але, здається, це не працює. Я не знаю, як це зробити.


9
Віддайте перевагу $ (foo) над задніми "foo" , тому що ви можете вкласти його, і це легше відрізнити від апострофів.
користувач невідомий

1
До речі, вам потрібно визначити функцію ( valid) перед тим, як викликати її.
wjandrea

Відповіді:


344

Повернене значення зберігається в $?. 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.


Це добре ... я можу провести помилку на виході ?? !! , тому що в цьому випадку у мене є 2 помилки: помилка команди "текст", наприклад, файл не знайдено, і моя помилка "текст". Що в цьому випадку, наприклад, не вдалося
moata_u

@moata_u: ви можете зберігати значення у змінній, як показано у моїй відповіді.
Лекенштейн

@moata_u: Вам потрібно поставити а ;перед elseі fi: `якщо ...; тоді ...; ще ...; fi
Лекенштейн


1
@Blauhirn [ $? ](або рівнозначно test $?) не працює, оскільки $?оцінює число (0, 1 і т.д.), яке не є нульовим. Дивіться документи дляtest : "Якщо EXPRESSION пропущено, 'test' повертає помилкове значення. Якщо EXPRESSION є одним аргументом, 'test' повертає false, якщо аргумент є недійсним, а інакше інакше."
Лекенштейн

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/TestsAndConditionss пояснює ifбільш докладно.


Що робити, якщо ви хочете зробити щось інше, ніж розгалуження, як зберігання булевого сигналу, невдало чи не в .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. Однак деякі утиліти будуть писати помилки в stdout (навіть якщо це погана практика). У цьому випадку ви можете опустити 2 з перенаправлення, але ви втратите будь-який вихід з команди. Цей метод перевірки успіху хороший для простої потрійної логіки, але для більш складної поведінки найкраще перевірити $?успішність команди або скористатися ifметодом блоку, викладеним у відповіді @ geirha.
Бендер найбільший

17

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

Отже, щось на кшталт;

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

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


Це добре ... я можу провести помилку на виході ?? !! , тому що в цьому випадку у мене є 2 помилки: помилка команди "текст", наприклад, файл не знайдено і моя помилка "текст", яка, наприклад, не вдалася, наприклад
moata_u

@moata_u, дивіться mywiki.wooledge.org/BashFAQ/002
geirha

5
command && echo $? || echo $?

Ви маєте на увазі command; echo $??
Хав'єр Буцці

Ні, мій рядок правильний, він дає фактичний код результату як число, незалежно від успіху чи невдачі.
modrobert

1
Добре, будь ласка, поясніть мені відмінності: true && echo $? || echo $?/ true; echo $?і false && echo $? || echo $?/ false; echo $?- ви знайдете, вони роблять точно те саме: D
Хав'єр Буззі

Так, такий же результат, але без умови. Первісне запитання було "Як перевірити, чи вдала команда?", Це ґрунтувалося на попередніх відповідях. Я припускаю, що кращим прикладом буде:command && echo "success: $?" || echo "fail: $?"
modrobert

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

але це вже не набагато коротше, ніж перший приклад.


1
конструктивна критика?
afuna

0

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

execute [INVOKING-FUNCTION] [COMMAND]

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

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

Натхненний художнім виробництвом:


-2

якщо [$ (команда)]; потім відлуння "досягти успіху"; фі


3
trueвдається, if [ $(true) ]; then echo "succeed"; fiале succeedне друкується. Насправді це ніколи не перевіряє, чи commandвдалося це зробити. Це слід просто використовувати, if commandяк на посаді гейри . $( )- це підміна команд . [ ]є умовним виразом . Відсутність розбиття слів і розширення імені файлів , це в основному перевіряє, чи commandбув вихід.
Елія Каган
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.