Почему первый код возврата 20 не остановил l oop?
Вы правы, что rsync
перехватывает определенные сигналы и выходит с RERR_SIGNAL
(20).
Как разрешить ловушке ловить сигнал SIGINT, но rsyn c, если нет, что мне делать?
Поскольку rsync
имеет свои собственные обработчики, вы ничего не можете сделать (могли бы использовать некоторые хаки для переопределения обработчиков сигналов в rsync
, например, LD_PRELOAD
. Но это может быть излишне сложно). Поскольку ваши ловушки находятся в текущей оболочке, вы не будете знать, была ли сигнализирована «команда» или выход с ненулевым значением.
Я бы предположил, что вы хотите, чтобы ваш retry
был обобщенным c, и вам не нужна специальная обработка rsync
(например, другая команда может завершиться с 75 для сигналов, и вы не не хочу иметь дело с особыми случаями.)
Проблема в том, что ваши обработчики ловушек не активны, так как сигнал получен текущим процессом, запущенным процессом (rsync
). Вместо этого вы можете запустить команду в фоновом режиме и дождаться ее завершения. Это позволит вам поймать сигналы от retry
. Получив сигнал, он просто убивает дочерний процесс.
#!/bin/bash
retry()
{
declare -i number=$1
declare -i i
declare -i pid
declare -i interrupted=0
trap "echo Exiting...; interrupted=1" SIGINT SIGTERM SIGQUIT
shift
# Turn off "monitor mode" so the shell doesn't report terminating background jobs.
set +m
for ((i = 0; i < number; ++i)); do
echo "\n-- Retry ${i}th time(s) --\n"
$@ &
pid=$!
# If command succeeded, break
wait $pid && break
# If we receive one of the signals, break
[[ $interrupted == 1 ]] && kill $pid && break
done
# Switch back to default behaviour
set -m
trap - SIGINT SIGTERM SIGQUIT
}
Обратите внимание, что SIGKILL
не может быть перехвачен. Так что нет смысла ставить ловушку для этого. Итак, я удалил его.