LINUX.ORG.RU
решено ФорумAdmin

Дублируются процессы


0

1

Всем привет. Прошу дать ответ на этот странный для меня момент.

Есть некий скрипт script.php

Запускаем его от простого пользователя

php /var/www/script.php

Далее выполняем команду

ps -ef | grep -v grep | grep "/var/www/script.php" 
userName 32253 32155  1 13:46 pts/2 00:00:00 php /var/www/script.php

убиваем все процессы

sudo killall php -9

Теперь запускаем этот же скрипт от рута

sudo php /var/www/script.php

Снова выполняем

ps -ef | grep -v grep | grep "/var/www/script.php"

И уже видим вот что

root     32631 32155  0 13:49 pts/2    00:00:00 sudo php /var/www/script.php
root     32632 32631  1 13:49 pts/2    00:00:00 sudo php /var/www/script.php

Почему выдаётся что запущено два процесса?

В случае если поставить данный скрипт в крон от рута

sudo crontab -e 
* * * * * php /var/www/script.php

Команда

ps -ef | grep -v grep | grep "/var/www/script.php"

Выдаёт вот что

root 699 687 0 13:53 ? 00:00:00 /bin/sh -c php /var/www/script.php
root 700 699  0 13:53 ? 00:00:00 php /var/www/script.php

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

if( ( $countPR = ( int ) exec( 'ps -ef | grep -v grep | grep "' . __FILE__ . '" | wc -l' ) ) > 1 ){
    
    echo 'Proccess (' . $countPR . ')' . PHP_EOL;
    die();
    
}

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


Хм, получилось избавиться от запуска доп.процессов добавив к команде

* * * * * php /var/www/script.php > /dev/null &

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

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

Скорее всего что-то в логике работы самого php. Возможно он пытается дропать привилегии при запуске от рута. Но так как это у тебя не настроено - то он просто порождает новый процесс fork-ом, не делая вызов setuid.

А вообще - зачем запускать процесс php от рута? И даже если это нужно - мешает ли тебе тот факт, что процесса запущено 2?

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

Возможно, потому что sudo. Первый процесс - sudo с параметрами, второй - собственно php. И у меня ощущение, что у вас ошибка в копипасте: у второго процесса не должно быть «sudo».

Насчет крона. Вообще говоря, он все команды запускает в шелле (по умолчанию /bin/sh, но его можно изменить, задав в кронтабе переменную SHELL=...). Не знаю, почему перенаправление вывода изменяет это поведение, надо ман почитать..

Kiborg ★★★ ()

в первом случае (при запуске через sudo) два процесса это сам sudo и его дочерний процесс php. Почему-то у тебя видны два процесса sudo, что странно. попробуй ps --forest и посмотри, кто чей сын.

во втором случае (через крон) тоже создается два процесса: первый это шелл, которому отдается команда выполнить скрипт, а второй - это сам php.

ddos3 ()

Абсолютно нормальная ситуация, так работают крон, шелл и sudo. Следи за выводом ps. Когда ты что-то запускаешь через sudo, то экземпляр шелла (в твоем случае pid 32155) форкается и форк выполняет бинарник sudo (pid 32631). sudo, в свою очередь, делает setuid, чтобы получить привилегии суперпользователя (в данном случае), опять же форкается и форк выполняет интерпретатор пыха (pid 32632). Получается, что выполняются два процесса - sudo и интерпретатор пыха. Вывод ps получается немного загадочным в силу того, что командная строка процесса может быть переопределена самим процессом, и sudo выставляет ее именно таким образом.

Когда ты ставишь пых в крон, то крон запускает его через /bin/sh -c. Крон (pid 687) форкается и форк запускает шелл с ключом -c (pid 699), а шелл в свою очередь форкается и форк выполняет пых (pid 700). Тут вывод ps весьма очевиден.

Выход для тебя - использовать lock-файлы вместо вывода ps. Ну, типа, твой скрипт запускается, создает файл вида /tmp/script-running-4lkjgd5 и при каждом запуске проверяет есть ли файл /tmp/script-running-*. Если есть, то дохнет сам. Только надо какую-то процедуру клинапа придумать на случай если у тебя машина перезапустится и скрипт не успеет удалить lock-файл.

Как-то так.

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

+1, lock-файлы как-то менее костыльный костыль. В него обычно PID пишут, а при запуске смотрят: если PID еще живой (опционально: и его команда запуска содержит script.php), то уходим. Если нет - пихаем туда наш PID и работаем.

Kiborg ★★★ ()

ps -ef | grep -v grep | grep «/var/www/script.php»

man pgrep

вместо наколенных костылей с локфайлами используй системные костыли flock

* * * * * flock -n /var/run/mysuperscript.lock -c /var/www/script.php

zolden ★★★★★ ()

ps axfu ответит на твой вопрос. только чур не грепать

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

Всем огромное спасибо за овтеты!!!

Как я теперь понял при запуске из крона

выдаются два процесса

root 699 687 0 13:53 ? 00:00:00 /bin/sh -c php /var/www/script.php
root 700 699  0 13:53 ? 00:00:00 php /var/www/script.php

И получатся первый будет висеть и ждать окончания работы второго (дочерного), а выполнив команду

* * * * * php /var/www/script.php > /dev/null &

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

Но использование flock

* * * * * flock -n /tmp/script.lock -c 'php /var/www/script.php > /dev/null &'

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

Остаётся последний вопрос, если ли у этого flock подводные камни? Скажем, например, после завершения работы скрипта при определённых условиях не будет снята блокировка с lock-файла.

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

Полезная штука, спасибо.

Я всю жизнь проверял наличие /var/run/script.run, проверял наличие процесса с записаным там PID, если не находил первого или второго - писал в этот файл свой PID. А оказывается, можно гораздо проще.

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

root 699 687 0 13:53 ? 00:00:00 /bin/sh -c php /var/www/script.php root 700 699 0 13:53 ? 00:00:00 php /var/www/script.php

это значит что вы запускаете процес /bin/sh, в котром запускается php.
при запуске sudo php blahblahblah. вы запускаете процес sudo который запускает процес php.
что мешает просто запускать /usr/bin/php blahblahblah ?
вы уверены что вам нужен flock? я не вижу в нем ни какой необходимости

expelled ★★ ()
root 699 687 0 13:53 ? 00:00:00 /bin/sh -c php /var/www/script.php
root 700 699  0 13:53 ? 00:00:00 php /var/www/script.php

ну всё правильно: 699 это шелл, а 700 это пхп. Пхп запускается шеллом.

А «от юзера» ты просто в консольке набираешь, и родителя bash'а не считаешь.

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

Не знаю, почему перенаправление вывода изменяет это поведение, надо ман почитать..

меняет поведение & (ампресанд) после команды.

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

А оказывается, можно гораздо проще.

да, только не везде оно есть и работает.

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

Хм, а разве flock есть не на всех *nix системах? Если можно, пожалуйста, поподробней. Где его может не быть и где может не работать?

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

Откуда кстати пошло это идиотское выражение «*nix системы»?
Под него ни linux, ни бсд, ни что-то еще кроме unix не подходит.

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

Буду знать. Но с серверами на макоси я вряд ли когда столкнусь.

идиотское выражение «*nix системы»?

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

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

Хм, а разве flock есть не на всех *nix системах? Если можно, пожалуйста, поподробней. Где его может не быть и где может не работать?

я думал вы про pgrep. А flock вроде везде есть(в смысле в Linux, это AFAIK линукс-специфика. В Slackware это работает, а вот в гей-ос вряд-ли).

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