LINUX.ORG.RU
ФорумAdmin

Помогите разобраться с Bash и Ctrl+C

 , , , ,


0

2

Доброго времени суток!

На днях писал очередной скрипт автоматизации на bash и столкнулся с забавной штукой - скрипт, который верой и правдой работал на Ubuntu 10.04 перестал корректно отрабатывать на Cent OS 6.2 и 6.3, а также воспроизвел ситуацию на Fedora 16. В общем вот что надо для воспроизведения:

/etc/init.d/testsh

#! /bin/bash # # testsh Test bash # case «$1» in start) /tmp/starttestscript.sh & ;; stop) ;; status) ;; restart|reload|force-reload) $0 stop $0 start rc=$? ;; *) echo $«Usage: $0 {start|stop|status|restart|reload|force-reload}» exit 2 esac

exit $rc

/tmp/sarttestscript.sh

#! /bin/bash - скрипт запуска проекта (когда запускается система, она пишет log-файл, тут я искуственно такой log-файл создал. tcpdump >> /tmp/testfile.log

/tmp/sborkatestscript.sh - скрипт запуска процесса сборки проекта, запуска системы и вывод лога запуска на экран.

#! /bin/bash /etc/init.d/testsh start tail -f /tmp/testfile.log

Так вот, мой порядок действий: 1. Запускаю скрипт /tmp/sborkatestscript.sh и на экране у меня начинает бежать лог. 2. В это время смотрю работает ли моя «служба» при помощи ps -f -C tcpdump --no-headers мне выводится что-то в роде: # ps -f -C tcpdump --no-headers tcpdump 5804 5802 5 15:27 pts/2 00:00:00 tcpdump 3. Как только я «насмотрелся лога» после запуска системы я выхожу из tail -f при помощи Сtrl+С 4. Далее хочу проверить ка там «служба» и вот что получаю # ps -f -C tcpdump --no-headers # т.е. такого демона получается не запущено.

Не могу понять почему так происходит. Ведь запуск был от другого скрипта, да и как я понимаю ctrl+C должен повлиять то был только на прекращение tail. Если посмотреть в pstree, то ИМХО не должно убивать запущенный процесс ├─konsole─┬─bash │ ├─bash───su───bash───sborkatestscrip───tail │ ├─bash───su───bash───pstree │ ├─bash───su───bash │ └─{konsole} ├─starttestscript───tcpdump Ну и самое главное, на Ubuntu то у меня точно таой же скрипт работал. Помогите пожалуйста разобраться как быть, мне надо работать именно по воспроизведенной на простых скриптах схеме и именно через tail.

Заранее большое спасибо!


ctrl+C должен повлиять то был только на прекращение tail.

нет, при этом посылается SIGINT всем процессам текущей группы данного терминала.
Чтобы твой «демон» не убивался, надо его запускать не просто с '&',
а через 'setsid' или, лучше, с помощью штатных средств скриптов инициализации (к сожалению, у меня другая система, не могу посмотреть,
что-нибудь типа start-stop-daemon...).

ABW ★★★★★ ()
Ответ на: комментарий от ABW

посылается SIGINT всем процессам текущей группы данного терминала

В каких шеллах/терминалах/ядрах?
Почему в его убунте все работает?

zolden ★★★★★ ()
Ответ на: комментарий от zolden

Вот и я не пойму почему все работает. Изначально сервер разработки был на Ubuntu (так сделали до меня) и скрипт сборки проекта я писал именно на этом сервере. Все работало как часы (по тому примеру как я сделал в описании топика) но когда стал обновлять сервак, а точнее обновил все работало ок, кроме описанной выше схемы. Что на CentOS 6.2, что на Centos 6.3 что на моем рабочем компе под Fedora 16. Сейчас Ubuntu к сожалению под рукой нет, чтобы снова проверить и чуть ли не видеоролик записать.

Помогите пожалуйста разобраться.

MakPol ()
Ответ на: комментарий от yozan

Понятно то понятно, но снова в теории... Сейчас у меня вот что:

/etc/init.d/testsh

#! /bin/bash
#
# testsh       Test bash
#
case "$1" in
  start)
nohup /tmp/starttestscript.sh &
#пробовал также: 
#/tmp/starttestscript.sh &
#disown
        ;;
  stop)

        ;;
  status)
        ;;
  restart|reload|force-reload)
        $0 stop
        $0 start
        rc=$?
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
        exit 2
esac

exit $rc

/tmp/sborkatestscript.sh

#! /bin/bash
/etc/init.d/testsh start
tail -f /tmp/testfile.log

/tmp/starttestscript.sh

#! /bin/bash  
tcpdump >> /tmp/testfile.log

Запускаю /tmp/sborkatestscript.sh все ок, лог идет (отображается благодаря tail -f Смотрю на процессы:

# ps -f -C tcpdump --no-headers 
tcpdump  22084 22082  0 09:12 pts/6    00:00:00 tcpdump
Жму Ctrl-C Снова смотрю на процессы:
# ps -f -C tcpdump --no-headers 
#
Когда работает, то pstree выдает: [IMG]http://s40.radikal.ru/i087/1207/ef/66009a8a5a1b.png[/IMG]

MakPol ()
Ответ на: комментарий от zolden

Почему в его убунте все работает?

потому как

(выдержка man nohup)

NOTE: your shell may have its own version of nohup, which usually supersedes the version described here. Please refer to your shell's documentation for details about the options it supports.

и https://wiki.ubuntu.com/DashAsBinSh/

из шел-скриптов внешние утилиты надо запускать с путями, чтобы не путать со встроенными командами shell и шебанг пишется без пробела :)

p.s. в LOR-code надо добавить тег [man] чтобы цитаты из man`ов выделялись красным цветом

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MakPol

Покажите вместо pstree кусок вывода

«ps -eo pid,sid,pgid,tpgid,user,args --forest»

для этих процессов (tcpdump и tail).

mky ★★★★★ ()
Ответ на: комментарий от zolden

1) В любых, это POSIX-поведение драйвера терминала в каноническом режиме, см. stty(1) и далее.
2) Не знаю и посмотреть сейчас не могу за отсутствием таковой.
Впрочем, выше уже вроде что-то написали.

ABW ★★★★★ ()
Ответ на: комментарий от MakPol

сам-то tcpdump тоже нужно форкнуть. и всё-таки вывод nohup лучше занулять, что-бы он не гадил в nohup.out и форкать его не нужно - он сам форкнется

yozan ()
Ответ на: комментарий от MakPol

Вообще-то, nohup в данном конкретном случае ни при чем.
Как я уже замечал, Ctrl-C обеспечивает всех SIGINT,
так что нужно или запускать через setsid (без &),
либо хотя бы маскировать SIGINT перед запуском:

  ( trap '' INT ; /tmp/script & )
(круглые скобки существенны).
Кстати, вероятнее всего в Ubuntu и работало из-за запрещения SIGINT shell-ом.

ABW ★★★★★ ()
Ответ на: комментарий от ABW

В общем разобрался, добрые люди помогли. 1. Можно выходить из tail -f не ^C, а ^4 или ^\ 2. В скрипте /etc/init.d/testsh сделать вот так: set -m /tmp/starttestscript.sh &

Всем спасибо за советы.

MakPol ()
Ответ на: комментарий от ABW

Кстати, вероятнее всего в Ubuntu и работало из-за запрещения SIGINT shell-ом.

Это вот и странно. Если смотреть тот bash, который в Scientific Linux 6 (наверное у ТС в CentOS 6.2 такой же), то получается так. С включенным Job controll каждый фоновый процесс идёт в своей группе (setsid()), и, понятно, не может получить SIGINT от терминала. Если Job controll выключен (set +m), то все потомки bash работают в одной группе процессов и получает сигналы с клавиатуры. Но, в этом случае bash перед exec() делает игнорирование (SIG_IGN) для сигналов SIGINT и SIGQUIT. В man bash про это написано обтекаемо:

Background processes are those whose process group ID differs from the terminal’s; such processes are immune to keyboard-generated signals.

tcpdump, который «умирал» у ТС, устанавливает свой обработчик SIGINT, поэтому ваш способо с «trap» не годится.

В Убунту работало скорее всего потому, что dash всегда запускает фоновые процессы с setsid(), но это утверждение хорошо бы проверить.

mky ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.