Как перехватить код выхода в скрипте Bash - PullRequest
39 голосов
/ 15 марта 2011

В моем bash-коде много точек выхода. Мне нужно выполнить некоторую работу по очистке при выходе, поэтому я использовал trap для добавления обратного вызова для выхода, например:

trap "mycleanup" EXIT

Проблема в том, что есть разные коды выхода, мне нужно выполнить соответствующие работы по очистке. Могу ли я получить код выхода в mycleanup?

Ответы [ 3 ]

44 голосов
/ 15 марта 2011

Я думаю, вы можете использовать $? для получения кода выхода.

43 голосов
/ 13 мая 2014

Принятый ответ в основном правильный, я просто хочу уточнить.

Следующий пример хорошо работает:

#!/bin/bash

cleanup() {
    rv=$?
    rm -rf "$tmpdir"
    exit $rv
}

tmpdir="$(mktemp)"
trap "cleanup" INT TERM EXIT
# Do things...

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

trap "rv=$?; rm -rf $tmpdir; exit $rv" INT TERM EXIT

Вместо этого вы должны экранировать переменные $rv и $?:

trap "rv=\$?; rm -rf $tmpdir; exit \$rv" INT TERM EXIT

Возможно, вы также захотите экранировать $tmpdir, так как он будет оценен, когда будет выполнена строка прерывания и если значение tmpdir изменится позже, что не даст ожидаемого поведения.

Редактировать: Используйте shellcheck , чтобы проверить ваши bash-скрипты и быть в курсе таких проблем.

4 голосов
/ 19 января 2017

Я обнаружил, что лучше отделить ловушку EXIT от ловушки для других сигналов

Пример скрипта тестирования ловушек ...

umask 77
tmpfile=`tmpfile.$$`
trap 'rm -f "$tmpfile"' EXIT
trap 'exit 2' HUP INT QUIT TERM

touch $tmpfile
read -r input 

exit 10

Временный файл очищен. Выходное значение файла 10 сохраняется! Результатом прерываний является выходное значение 2

В основном, если вы не используете «выход» в ловушке EXIT, он будет выходить с сохранением исходного значения выхода.

ASIDE: обратите внимание на цитирование в ловушке EXIT. Это позволяет мне изменить файл, который необходимо очистить при жизни скриптов. Я также часто включаю тест на существование $ tmpfile varables, поэтому мне даже не нужно устанавливать его в начале скрипта.

...