В crontab перед управлением добавляют . $HOME/.profile
. Например:
0 5 * * * . $HOME/.profile; /path/to/command/to/run
Cron
ничего не знает о Вашей оболочке; это запускается системой, таким образом, это имеет минимальную среду. Если Вы хотите что-нибудь, необходимо было ввести это самим.
Спецификация POSIX не говорит многое об условиях, приводящих к выполнению прерывания ВЫХОДА, только о том, на что должна быть похожей его среда, когда это выполняется.
В оболочке пепла Busybox Ваш тест выхода прерывания не повторяет 'ПРЕРЫВАНИЕ' прежде, чем выйти или из-за SIGINT или из-за SIGTERM. Я подозревал бы, что существуют другие оболочки в существовании, которое не может проложить себе путь также.
# /tmp/test.sh & sleep 1; kill -INT %1
#
[1]+ Interrupt /tmp/test.sh
#
#
# /tmp/test.sh & sleep 1; kill -TERM %1
#
[1]+ Terminated /tmp/test.sh
#
Да, есть разница.
Этот скрипт выйдет, когда вы нажмёте Enter, или отправите ему SIGINT
или SIGTERM
:
trap '' EXIT
echo ' --- press ENTER to close --- '
read response
Этот скрипт выйдет, когда вы нажмёте Enter:
trap '' EXIT INT TERM
echo ' --- press ENTER to close --- '
read response
* Tested in sh, Bash, и Zsh. (больше не работает в sh, когда вы добавляете команду для запуска ловушки)
Также есть то, что сказал @Shawn: Ash и Dash не ловят сигналы с EXIT
.
Так что, для надежной работы с сигналами, лучше всего избегать ловушек EXIT
вообще, и использовать что-то вроде этого:
cleanup() {
echo "Cleaning stuff up..."
exit
}
trap cleanup INT TERM
echo ' --- press ENTER to close --- '
read var
cleanup
Уточнение последнего ответа, потому что у него есть проблемы:
# Our general exit handler
cleanup() {
err=$?
echo "Cleaning stuff up..."
trap '' EXIT INT TERM
exit $err
}
sig_cleanup() {
trap '' EXIT # some shells will call EXIT after the INT handler
false # sets $?
cleanup
}
trap cleanup EXIT
trap sig_cleanup INT QUIT TERM
Пункты выше:
Обработчики INT и TERM не завершают работу, когда я тестирую - они обрабатывают ошибку затем оболочка возвращается к завершению (и это неудивительно). Поэтому я гарантирую, что очистка завершится после этого, и в случае сигналов всегда используется код ошибки (а в другом случае нормального выхода код ошибки сохраняется).
С bash кажется, что выход в обработчике INT также вызывает обработчик EXIT, поэтому я разворачиваю обработчик выхода и вызываю его сам (который будет работать в любой оболочке независимо от поведения).
Я перехватываю exit, потому что сценарии оболочки могут завершиться до того, как достигнут конца - синтаксические ошибки, установка -e и ненулевой возврат, просто вызов exit. Вы не можете полагаться на то, что шелл-скрипт доберется до сути.
SIGQUIT - это Ctrl- \, если вы никогда его не пробовали. Предоставляет вам бонусную сердцевину. Так что я думаю, что это тоже стоит заманить в ловушку, даже если это немного неясно.
Прошлый опыт говорит, что если вы (как и я) всегда нажимаете Ctrl-C несколько раз, вы иногда поймаете это на полпути через часть очистки вашего сценария оболочки, так что это работает, но не всегда так идеально, как хотелось бы .
Это зависит от того, чего вы пытаетесь достичь и какие снаряды вы используете. Для bash
можно просто использовать EXIT
. Но не все оболочки вызывают обработчик EXIT
для SIGINT
/SIGTERM
.
Для них можно попробовать задать один обработчик на несколько сигналов (trap '...' INT EXIT
), но тогда он может вызываться несколько раз:
$ bash -c 'trap "echo trap" INT EXIT; sleep 3' & pid=$!; sleep 1; kill -INT $pid; wait
[1] 276923
trap
trap
[1]+ Done bash -c 'trap "echo trap" INT EXIT; sleep 3'
Так что либо вы пишете это с учетом этого, либо вы можете попытаться перенаправить все EXIT
обработчику:
$ bash -c 'trap "exit 123" INT; trap "echo EXIT \$?" EXIT; sleep 3' & pid=$!; sleep 1; kill -INT $pid; wait
[1] 286229
EXIT 123
[1]+ Exit 123 bash -c 'trap "exit 123" INT; trap "echo EXIT \$?" EXIT; sleep 3'
Но если вы настроили обработчик для SIGINT
, обычно вы хотите, чтобы он убивал скрипт с помощьюSIGINT
:
a.sh
:
trap 'exit 123' INT
trap 'echo EXIT $?; trap - INT; kill -INT $$' EXIT
sleep 3
$ bash h.sh & pid=$!; sleep 1; kill -INT $pid; wait $pid
[1] 236263
EXIT 123
[1]+ Interrupt bash h.sh
А в Debian < 10(dash < 0.5.10
)сигнал , убивающий скрипт (, если какой-либо)не передан .
Решение, которое я придумал:
set -eu
cleanup() {
echo "cleanup ($1)"
trap - INT TERM EXIT # avoid reexecuting handlers
if [ "$1" = 130 ]; then
kill -INT $$
elif [ "$1" = 143 ]; then
kill -TERM $$
else
exit "$1"
fi
}
trap 'cleanup 130' INT
trap 'cleanup 143' TERM
trap 'cleanup $?' EXIT
if [ "${1-}" = fail ]; then
no-such-command
fi
sleep 3
$ bash f.sh; echo $?
cleanup (0)
0
$ bash f.sh fail; echo $?
f.sh: line 20: no-such-command: command not found
cleanup (127)
127
$ bash f.sh & pid=$!; sleep 1; kill -INT $pid; wait $pid
[1] 282422
cleanup (130)
[1]+ Interrupt bash f.sh
$ bash f.sh & pid=$!; sleep 1; kill -TERM $pid; wait $pid
[1] 282458
cleanup (143)
[1]+ Terminated bash f.sh
Испытано в:
bash
:5.1.8
0.5.10
, 0.5.8
,0.5.7
busybox
)
dash
также не захватывает на простоEXIT
когда это получаетSIGINT/SIGTERM
. – maxschlepzig 29.10.2016, 19:50zsh
также - таким образом, возможноbash
единственная оболочка гдеEXIT
также соответствует сигналам. – maxschlepzig 29.10.2016, 19:59