Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей программы. Программа ловит сигнал SIGTERM для этих целей.Однако при reboot и halt мое приложение не получает этого сигнала, хотя есть сообщение
INIT: sending TERM signalвыдача команды killall myprog
приводит к обработеке моей программой сигнала SIGTERMТакое ощущение - что "прибивается" родительский процесс для моей программы (bash) - что приводит к немедленному завершению моей программы.
Дело ослажняется тем - что программа должна запускаться автоматически при старте ситемы на терминале tty1.
Как корректно решаются такие проблеммы в LINUX ?
Алексей.
>Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей
>программы. Программа ловит сигнал SIGTERM для этих целей.
>
>Однако при reboot и halt мое приложение не получает этого сигнала, хотя
>есть сообщение
>INIT: sending TERM signal
>
>выдача команды killall myprog
>приводит к обработеке моей программой сигнала SIGTERM
>
>Такое ощущение - что "прибивается" родительский процесс для моей программы (bash) -
>что приводит к немедленному завершению моей программы.
>
>Дело ослажняется тем - что программа должна запускаться автоматически при старте ситемы
>на терминале tty1.
>
>Как корректно решаются такие проблеммы в LINUX ?
>
>Алексей.1. создай нормальный init скрипт с PID файлом и т.д. и т.п.
или
2. запускай прогу через inittab (сто не есть правильно -- но оно может именно то , что нужно)З.Ы "родительский процесс для моей программы (bash) -" -- это что означает -- что программа есть шелл скрипт???
man init, man inittab и доки по sysvinit.
>>Нужно отследить момент завершения работы/перезагрузки ОС Linux и корректно завершить работу моей
>1. создай нормальный init скрипт с PID файлом и т.д. и т.п.Не понял, о чем идет речь. Нужно чтобы программа запускалась на терминале tty1
>или
>2. запускай прогу через inittab (сто не есть правильно -- но оно
>может именно то , что нужно)
Делаю следующее:
в /etc/inittab сторку
1:2345:respawn:/sbin/getty 38400 tty1
заменяю на
1:2345:respawn:/sbin/getty -n -l /etc/rc.d/autologinroot 38400 tty1
в файле autologinroot пишем
su -root -c "/bin/bash -li"
в каталоге /root создаю файл .bash_profile
if [ $(tty) == /dev/tty1 ] ; then
cd /myprog
/myprog/myprog
fi>З.Ы "родительский процесс для моей программы (bash) -" -- это что означает
>-- что программа есть шелл скрипт???Нет - C++ приложение.
Может про родительский процесс я и "погнал" :) я в Linux новичок.
Но по другому - обьяснить свои проблеммы не могу.
а зачем getty использовать -- просто
1:2345:respawn:/myprog/myprogили убери вовсе (закоментируй) "1:2345:respawn:/sbin/getty 38400 tty1" и запускай через screen -- ему можно указать на какой консоли робить.
А про PID -- так это обычно файлик такой -- в котором храниться информация о pid определённого запущенного процесса -- ну и обычно когда обрабатываются скрипты запуска/останова (init 3 ? init 5? init 6 ? init 0) -- так вот init6 (перезагрузка) и init0 (выключение) скрипты читают файлик -- и посылают сигнал процессу с этим пидом -- потом ждут когда процесс завершиться.
>а зачем getty использовать -- просто
>1:2345:respawn:/myprog/myprogПопробовал так (но через командный файл - связано с текущим каталогом) -
Моя программа запускается но имеются следующие побочные эффекты:
1) Прогамма не реагирует на на нажатия ^C (но может это даже к лучшему ;),
2) При выполнении reboot или halt моя программа успевает еще раз запуститься по respawn
на том терминале где делаем reboot.Что меня конечно не радует.
Похоже что в данном случае моя программа действительно получает SIGTERM но процесс init почемуто не смотря на то, что он собирается завершиться и перезапускает мое приложение.Кстати это по моему подтверждает гипотезу - что при моем способе запуска я не ловлю своим процессом SIGTERM именно потому, что bash "умирает" первым - и "прибивает" своих "деток".
>или убери вовсе (закоментируй) "1:2345:respawn:/sbin/getty 38400 tty1" и запускай через screen --
>ему можно указать на какой консоли робить.А можно пример что и как в данном случае прописать ?
>
>А про PID -- так это обычно файлик такой -- в котором
>храниться информация о pid определённого запущенного процесса -- ну и обычно
>когда обрабатываются скрипты запуска/останова (init 3 ? init 5? init 6
>? init 0) -- так вот init6 (перезагрузка) и init0 (выключение)
>скрипты читают файлик -- и посылают сигнал процессу с этим пидом
>-- потом ждут когда процесс завершиться.Это понятно - но как я понял - эти скрипты выполняются уже ПОСЛЕ того как были разосланы синалы SIGTERN и SIGKILL процессом init. И мой анализ PID в этих скриптах уже бессмысленен, т.к. приложение уже "умерло" не попрощавшись :)
В этом то ПОСЛЕ как раз и вся "засада".
а вот теперь надо учиться учиться и ещё раз учиться
>>а зачем getty использовать -- просто
>Моя программа запускается но имеются следующие побочные эффекты:
>1) Прогамма не реагирует на нажатия ^C (но может это даже
>к лучшему ;),
>2) При выполнении reboot или halt моя программа успевает еще раз запуститься
>по respawnп.1 - верно
п.2 - мой "косяк" - в процессе экспериментов - перенаправлял reboot и halt на свои скрипты - "убийцы" myprog :)Короче правильно остановить программу - сделать так - как говорили умные люди :)
1) строку inittab 1:2345:respawn:/sbin/getty 38400 tty1
заменяем на 1:2345:respawn:/myprog/run_myprog
2) в скрипте /myprog/run_myprog пишем
#!/bin/bash
cd /myprog
/myprog/myprog3) ну и не забываем в теле программы установить обработчик SIGTERM
Единственно что нужно учитывать - пауза между TERM и KILL сигналами выдаваемыми процессом init - достаточно мала. Заставитьбы init перед KILL дожидаться завершения моей myprog - былобы совсем хорошо.
>Это понятно - но как я понял - эти скрипты выполняются уже
>ПОСЛЕ того как были разосланы синалы SIGTERN и SIGKILL процессом init.
>И мой анализ PID в этих скриптах уже бессмысленен, т.к. приложение
>уже "умерло" не попрощавшись :)
>
>В этом то ПОСЛЕ как раз и вся "засада".Я думаю тебе поможет правильная демонизация твоего процесса!
Почему у тебя родительский процесс bash?? из за того что ты его из basha запустил? демонизируешь свою прогу и все корректно будет получать сигтерм!Поясни пожалуйста что значит
"Нужно чтобы программа запускалась на терминале tty1"
что это за программа? она обслуживает работу tty1? На нем больше кроме нее никто не работает? Твоя прога его на запись открывает? или она использует STDOUT полученный от bash, а тот получивший его в наследство от login, в свою очередь получивший от getty?Если нужно работать с tty1, то (ИМХО) надо убрать с tty1 всех этих демонов(вернее только getty :))! и открывать его через open 'dev/tty1'
если ты правильно выполнишь демонизацию своей проги, то ее родителем станет 1 процесс init, а значит она не умрет из за того что ее родителя скропостижно убили.
Вот проверь этот скрипт:
#!/usr/bin/perl -wuse strict;
use POSIX 'WNOHANG';my $quit = 0;
print "----------Base Start Programm------------------\n";
open(LOG, ">>", "daemon.log");
#Отвязываемся от вывода в текущи терминал
open(STDIN, '</dev/null') or die "Can't read /dev/null: $!";
open(STDOUT, ">>&LOG") or die "Can't write to LOG file: $!";
open(STDERR, ">>&LOG") or die "Can't error to LOG file: $!";
umask(0); #Сброс маски режима создания файлов
$ENV{PATH} = '/bin:/usr/bin';
#Выходим из текущего потока управления, создавая свой, а в текущем завершаемся.
die "Can't fork" unless defined (my $child = fork());
if($child) {
print "close parent, and stay demon";
exit 0; #Завершение родительского сеанса
}
#становимся лидером сессии
POSIX::setsid();
sub sig_worker {
my $sig = shift;
$quit++;
print "I get signal = $sig\n";
return;
}#Устанавливаем обработчик сигналов
$SIG{TERM} = $SIG{INT} = \&sig_worker;while(!$quit){
print "Please: Kill me!!!\n";
sleep 1;
}
#Определим причину по которой завершилась программа
if($quit) {
print "Exit by quit = $quit\n";
}print "---------------- End Programm---------------------\n";
close(LOG);
exit(0);