LINUX.ORG.RU

PID file


2

3

Задача демона или init script'a?
Кто должен заботиться о создании и удалении?

★★★★★
Ответ на: комментарий от jamy

Муторно это: надо модуль ядра фигачить. Зчем? Ведь все можно сделать намного проще.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

демон сам себя убивает если видит своего клона — ДЫ ЭТО ОХРЕНЕТЬ МОЖНО какой костыль!

Костыль.

делаешь при запуске демона — по отношению к блокировочному-файлу (не файлу устройства, а блокировачному файлу!) — ЭКСКЛЮЗИВНУЮ-НЕ_БЛОКИРУЮЩУЮ блокировку...

Кстати, надо будет в следующий раз попробовать с flock в shm побаловаться. Вполне возможно, что это будет проще.

PID-файлы вообще нужны не для того чтобы не было дубликатов демнов. а для других целей.

Ну да: чтобы быстро сделать kill -9.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Да я шутил. И даже если и воспринимать мое решение серьезно, то оно было нацеленно не на конечного пользователя, а на дистрибутивостроителей, им такой модуль ядра запилить не составит труда.

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

Вообще, да: глобальная блокировка на уровне ядра не помешала бы. Эдакий сисвызов, проверяющий уникальность запущенного процесса. Тогда не надо было бы придумывать эту чехарду с блокировками и PID-файлами.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Сис вызов - это не универсально. Ну к примеру нужно будет перенести этот демон на другую систему, а там в ядре нет такого сисвызова. Что тогда? А вот чтение из файла есть во всех системах, другое дело что этот файл будет виртуальным, ну так демону это знать и ни к чему

jamy
()

Задача демона или init script'a?

По порядку, для начала разберемся, зачем вообще нужен pid-файл. PID-файл init-скрипту нужен только для того, чтобы знать, какой процесс kill-ить по команде stop. И всё.

Зачем ему для этого pid-файл? Затем, что таких демонов в системе может быть много. Вообще, почти любых демонов может быть много. Может быть несколько http или ftp-серверов, если они висят на разных портах. Может быть даже несколько init/udev демонов, если один из них запущен в чруте или контейнере.

Не, требуется просто проконтроллировать, чтобы демон был только один. Есть другие методы?

Если демон только один, то зачем вообще PID-файл? Можно стопать процесс killall-ом.

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

Если демон только один, то зачем вообще PID-файл? Можно стопать процесс killall-ом.

OK, а чтобы обеспечить единичный запуск flock'a должно быть достаточно, так?

UVV ★★★★★
() автор топика

PID файл - пережиток прошлого :3

Но вообще демона, разумеется. Ему виднее, где его основной инстанс

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

OK, а чтобы обеспечить единичный запуск flock'a должно быть достаточно, так?

Любой способ подойдет. Если flock подходит, то можно и flock (сам flock будет тоже висеть в памяти). Если скучно, можно даже cgroup создать, они как раз из баша легко управляются.

Но нужно ли вообще обеспечивать единичный запуск? В смысле, если это — демон, и он слушает какой-нибудь TCP/UDP-порт или юникс-сокет, то вторая его копия просто не запустится, потому что порт будет уже занят. То есть дополнительно ничего обеспечивать и не надо...

anonymous
()
Ответ на: комментарий от vasily_pupkin

Тебе не кажется, что это задача менеджера служб? :]

А вам обоим не кажется, что open(O_EXCL) в ядре уже есть? ;)

anonymous
()
Ответ на: комментарий от vasily_pupkin

Это смотря как посмотреть. По большому счету-то все равно ведро занимается блокировками! Ну и почему бы не заставить его выполнять уникальную блокировку?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Батенька, это — блокировка файла! А мы про блокировку демона говорим — в смысле, чтобы он был уникальным.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Батенька, это — блокировка файла! А мы про блокировку демона говорим — в смысле, чтобы он был уникальным.

Какая разница? Все равно демон будет решать, хочет он быть уникальным или нет. И для проверки уникальности вы предлагаете делать какой-нибудь системный вызов. Вот open(O_EXCL) и есть этот вызов.

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

Все равно демон будет решать, хочет он быть уникальным или нет

Дык, а если файл удалят?

Но, опять-таки, я согласен: если сделать «файл» в разделяемой памяти и повесить на него блокировку, то никаких чудачеств, вроде тех, что я в начале приводил (PID-файлы + просмотр /proc) делать не надо будет.

Кстати, сдается мне, flock — и есть тот самый open(O_EXCL). Но я — не программист, точных подробностей не знаю.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Дык, а если файл удалят?

А это не баг, это фича! Администратор должен иметь возможность обойти блокировку, если ему позарез надо что-то по-быстрому накостылять в системе: вручную запустить вторую копию процесса, например, потому что ему срочно так надо. И для этого он просто удалит файл. Случайный посторонний не сможет этот файл удалить, у него прав не будет.

Но для большинства демонов это и не нужно. Они итак открывают какой-нибудь порт или сокет, и вторая копия у них все равно не запустится.

никаких чудачеств, вроде тех, что я в начале приводил (PID-файлы + просмотр /proc) делать не надо будет.

PID-файлы вообще не для этого нужны. PID-файл — это указание init-скрипту, какому процессу посылать сигнал по stop-у. В общем случае демон может и сам форкнуться, и потомков себе нафоркать разных. Даже если инитскрипт отслеживает форки, он не будет знать, кому посылать SIGTERM. Вот для этого и нужен PID-файл. С его помощью демон однозначно сообщает init-скрипту PID процесса, которому надо сигналить.

Кстати, сдается мне, flock — и есть тот самый open(O_EXCL). Но я — не программист, точных подробностей не знаю.

Ну да. Но это — плюс-один процесс в памяти, некоторым это не нравится. А некоторые просто не хотят, чтобы демон зависел от внешних программ.

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

Администратор должен иметь возможность обойти блокировку, если ему позарез надо что-то по-быстрому накостылять в системе

Какая-то блондинистая система получается: либо можно, либо нельзя, либо «нельзя, но если очень хочется, то можно».

Если надо убить демона, его надо убить по-человечески, через принятую у этого демона систему запуска/остановки. А запускать вторую копию демона — вообще чревато.

PID-файл — это указание init-скрипту, какому процессу посылать сигнал по stop-у.

init при poweroff'е или reboot'е просто вызывает kill5. И не парится. Ему эти PID-файлы не нужны.

В общем случае демон может и сам форкнуться, и потомков себе нафоркать разных.

Тогда уж демон в ответе за кого приручил потомков. А вообще, если он делает форки, то все равно остается основной управляющий процесс, который при прибитии убивает остальных.

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

Но это — плюс-один процесс в памяти

Откуда? flock выполняет тот же процесс, никаких левых процессов вызывать не надо. А как он помирает, open «отваливается» и блокировка снимается. А вот ядро — да, что-то там делает. Но таки любая блокировка требует каких-то действий от ядра. Нельзя так просто взять, и обеспечить уникальность запуска процесса, не привлекая для этого костылей. Либо привлекай на помощь ядро, либо делай специальные проверки.

А некоторые просто не хотят, чтобы демон зависел от внешних программ.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Администратор должен иметь возможность обойти блокировку, если ему позарез надо что-то по-быстрому накостылять в системе

Какая-то блондинистая система получается: либо можно, либо нельзя, либо «нельзя, но если очень хочется, то можно».

Проверка на эксклюзивность в любом случае добровольна. Не важно, как она сделана, через системный вызов, файл или что-то еще. Если хочет — демон может проверить. Если не хочет, может не проверять. Ситуации же разные могут быть. Скажем, одинаковые демоны из разных чрутов вполне могут работать в одной системе одновременно.

блондинистая система

Наоборот! Блондинистая система — это винда. Она стремится быть умнее своих пользователей и за них решать, что правильно. Юниксы издавна были хороши именно тем, что не выпендривались, а делали свою работу, но делали ее хорошо, и не мешали админу делать его работу. Админ — это особый случай. Если ему что-то очень хочется, то ему можно. У него могут быть на то причины.

Если надо убить демона, его надо убить по-человечески, через принятую у этого демона систему запуска/остановки.

А вдруг какая-то экстремальная ситуация, и админу важно, например, убить демон SIGKILLом, чтобы он не отправил какой-нибудь посмертный сигнал потомкам? Мало ли что в жизни бывает.

А запускать вторую копию демона — вообще чревато.

Если админ удаляет лок-файлы, значит он знает, что делает. На то он и админ. :)

init при poweroff'е или reboot'е просто вызывает kill5. И не парится. Ему эти PID-файлы не нужны.

А при init 3? А при invoke-rc.d myservice restart?

А вообще, если он делает форки, то все равно остается основной управляющий процесс, который при прибитии убивает остальных.

Во-первых, не всегда. Может быть несколько равноправных процессов, каждому из которых надо сигналить в случае остановки (и тогда в PID-файле будет несколько PID-ов). Во-вторых, да, остается, но как скрипт должен узнать, кому из дерева форкнувшихся процессов нужно сигналить? Вот для того, чтобы инитскрипт знал, кому из них посылать сигнал, и придумали PID-файлы.

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

Э... Что значит «лучше»? Это может быть банально невозможно. Каким образом, например, nginx будет создавать php-инстансы в виде потоков?

Откуда? flock выполняет тот же процесс, никаких левых процессов вызывать не надо.

Запусти flock и посмотри. :) Или ты путаешь flock с fghack-ом?

anonymous
()
Ответ на: комментарий от Eddy_Em

Откуда? flock выполняет тот же процесс

А. Блин. Мы о разных вещах говорили.

Есть ядерная функция flock(2), в паре с open() она позволяет демону повесть блокировку на файл, и тогда второй демон, который попытается это сделать, обломится и поймет, что он не один.

Есть утилита flock(1). Эта утилита использует ту же самую функцию flock для той же самой цели, но снаружи от демона:

$ flock -xn /var/lock/myservice.lock /usr/bin/myservice
Использование этой утилиты позволяет запускать любой процесс с проверкой на уникальность, но сама утилита тоже висит в памяти. Как бонус эту утилиту можно использовать даже внутри баш-скрипта вместо мутекса (пример есть в мане).

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

Если админ удаляет лок-файлы, значит он знает, что делает

Выдадим админу гранатомет — пусть отстреливает себе ногу.

А при init 3? А при invoke-rc.d myservice restart?

А там службы управления демонами работают. Так что, тоже все ОК. Они-то и на 6 уровне работают, но «на всякий пожарный» еще и kill5.

как скрипт должен узнать, кому из дерева форкнувшихся процессов нужно сигналить?

А вот была бы «ядреная» блокировка, PID-файл был бы не нужен.

Каким образом, например, nginx будет создавать php-инстансы в виде потоков?

Без понятия. Я с пыхпыхом никогда не работал. А CGI запускать могут и потоки httpd/nginx.

Запусти flock и посмотри

Сделал файлик для проверки:

#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

main(){
	int i, fd;
	fd = open("lock", O_WRONLY);
	FILE *f = fdopen(fd, "w");
	flock(fd, LOCK_EX);
	for(i = 0; i < 60; i++){
		fprintf(f, "%d\n", i);
		fflush(f);
		sleep(1);
	}
	close(fd);
}
Скомпилировал, запустил. Никаких дополнительных процессов не создается:
     |-terminal-+-bash---su---bash---yaourt---yaourt
     |          |-bash---mc---bash---a.out 
(нижняя строчка)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Есть утилита flock(1)

Ясен пень, она висит отдельным процессом. Но я-то про демона говорил, который сам блокировку запускает, а не о инит-скрипте.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Если админ удаляет лок-файлы, значит он знает, что делает

Выдадим админу гранатомет — пусть отстреливает себе ногу.

Если гранатомет нужен ему для работы, то он должен лежать в репозитории.

А там службы управления демонами работают. Так что, тоже все ОК. Они-то и на 6 уровне работают, но «на всякий пожарный» еще и kill5.

Вот эти самые службы управления и узнают PID процесса, которому надо посылать синал, через PID-файлы. Как иначе они могли бы его узнать.

как скрипт должен узнать, кому из дерева форкнувшихся процессов нужно сигналить?

А вот была бы «ядреная» блокировка, PID-файл был бы не нужен.

Как ядерная блокировка позволит узнать скрипту, какому процессу посылать сигнал?

Ты путаешь две разные задачи: задачу проверки уникальности процесса и задачу получения PID-ов тех, кому посылать сигнал. Обе задачи нужны далеко не всем. В некоторых задачах нужна только проверка уникальности, в других — только PID-ы. Например, init-скрипту обычно не нужна проверка уникальности, но нужны PID-ы. А скрипту, который запускается по крону, может быть не нужен PID, но зато нужна проверка уникальности, чтобы не запустить вторую копию, если предыдущая еще не завершилась.

Без понятия. Я с пыхпыхом никогда не работал. А CGI запускать могут и потоки httpd/nginx.

Попробуй запустить внешнюю программу не отдельным процессом, а внутри потока того же процесса. :)

Сделал файлик для проверки ... Никаких дополнительных процессов не создается

Да, все верно. Если использовать утилиту flock, то будет дополнительный процесс, а если использовать функцию flock, то не будет. О том и шла речь, что не всем подойдет утилита, потому что будет лишний процесс в памяти.

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

Как ядерная блокировка позволит узнать скрипту, какому процессу посылать сигнал?

А почему бы не сделать killall и не париться?

Попробуй запустить внешнюю программу не отдельным процессом, а внутри потока того же процесса. :)

Элементарно: поток делает fork, сам помирает, а его потомок «превращается» в нужный CGI.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

А почему бы не сделать killall и не париться?

Когда пишешь скрипт для себя, и точно знаешь, что у тебя будет только один демон ­— можно и killall. Но если ты пишешь initscript для пакета, то нельзя. В инитскриптах почти никогда нельзя использовать killall, потому что процессов может быть несколько, а убивать надо далеко не всех.

Например, если у меня запущены два ftp-сервера, один на внешнем интерфейсе и второй на внутреннем, то по команде invoke-rc.d ftp-external stop должен остановится только один из них. А если в скрипте будет killall, то будут убиты оба.

Элементарно: поток делает fork, сам помирает, а его потомок «превращается» в нужный CGI.

Да, все верно. То есть CGI будет запущен отдельным процессом. Это относилось к фразе: «лучше таки создавать потоки, нежели процессы: все проще ведру будет подчищать мусор» — оно может и лучше, но не всегда это возможно.

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