Почему файлы «блокировки» используются в PHP, а не просто подсчитывают процессы? - PullRequest
0 голосов
/ 18 января 2019

Я видел много примеров, когда файл «lock» используется для отслеживания того, запущен ли сейчас PHP-скрипт.

Пример:

  1. скрипт запускается
  2. проверяет, заблокирован ли "/ tmp / lockfile"
  3. Если он заблокирован, выйдите. Если нет, заблокируйте файл и продолжайте

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

Однако, кажется, что это неправильный путь. Почему бы нам просто не проверить, запущен ли уже процесс, как этот?

if(exec("ps -C " . basename(__FILE__) . " --no-headers | wc -l") > 1){
  echo "Already running.";
  exit;
}

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

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Основная причина, по которой используются «блокирующие файлы», заключается просто в том, что они могут работать в любой хост-среде. Если вы можете «создать файл» и «заблокировать его», такой код будет работать ... где угодно.

Также - «нет ничего, что можно было бы получить , будучи« умным ». Известно, что эта хорошо известная стратегия работает хорошо - поэтому« бегите с ней ».

0 голосов
/ 18 января 2019

Основываясь на комментариях здесь и моих собственных наблюдениях, я составил список «за» и «против» обоих подходов:

flock метод:

плюсы:

  • Больше совместимо с операционными системами
  • Знание bash не требуется
  • Более распространенный подход, много примеров
  • Работает даже при exec() отключено
  • Может использовать несколько блокировок в одном файле, чтобы разрешить разные "режимы" для одного и того же файла одновременно

минусы:

  • Это не определенно. Если ваш файл блокировки удален внешним процессом / пользователем, вы можете получить несколько процессов. Если вы сохраняете файл блокировки в каталоге /tmp, это допустимая возможность, поскольку все в этом каталоге должно быть «временным»
  • При определенных обстоятельствах, когда процесс неожиданно умирает, блокировка файла может быть перенесена на несвязанный процесс (сначала я не поверил, но обнаружил, что это происходит (хотя и редко) в более чем 200 системах на основе Unix). , в 3 разных операционных системах)

exec("ps -C...") метод

плюсы:

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

минусы:

  • Работает только в Linux
  • требует, чтобы "exec" был включен
  • Если вы измените имя своего скрипта, это может привести к двойным процессам (и убедиться, что имя вашего скрипта не жестко запрограммировано в коде)
  • Предполагается, что ваш скрипт имеет только один запущенный "режим"

РЕДАКТИРОВАТЬ: я закончил с помощью этого:

if (exec("pgrep -x " . $scriptName . " -u ". $currentUser . " | wc -l") > 1)
{
  echo $scriptName . " is already running.\n";
  exit;
}

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


РЕДАКТИРОВАТЬ 2:

... Итак, после нескольких дней работы он тоже не идеален. Каким-то образом процесс запускался несколько раз на одном компьютере под одним и тем же пользователем. Я могу только предположить, что была какая-то проблема (не хватило памяти и т. Д.), Из-за которой pgrep ничего не возвращал, когда он должен был что-то возвращать.

Таким образом, это означает, что НИКОГДА метод flock и методы подсчета не являются на 100% надежными. Вам нужно будет определить, какой подход будет работать лучше для вашего проекта.

В конечном счете, я использую другое решение, которое хранит PID текущей задачи в файле блокировки, которое на самом деле не заблокировано с помощью flock. Затем, когда скрипт запускается, проверяет, существует ли файл блокировки, и, если он есть, получает содержимое (PID последнего запуска скрипта). Затем он проверяет, все ли еще выполняется, сравнивая содержимое /proc/#PID#/cmdline. с именем запущенного скрипта.

0 голосов
/ 18 января 2019

Во-первых, команда не верна. Когда я запускаю php test.php и команду

 ps -C test.php

пока ничего не получится. Вы можете использовать ps -aux|grep 'test.php' -c для получения номера процесса. Но exec("ps -aux|grep 'php test.php' -c"); номер возврата должен минус 2 - это реальный номер процесса

Причина, по которой файл блокировки используется чаще всего, заключается в том, что exec или другой командной функции требуется специальное разрешение, а именно disable_functions в конфигурации по умолчанию для php.ini.

Тестовый скрипт, подобный этому:

$count = exec("ps -aux|grep 'php test.php' -c");

if($count > 3){
  echo "Already running.".$count;
  exit;
}

while(1){
    sleep(20);
}
...