cron, каждую минуту проблемы с оперативной памятью

cron, каждую минуту проблемы с оперативной памятью

У меня есть cronjob, который запускает PHP на файле wordpress cron.php. Он в основном используется для планирования постов и, как мне кажется, может обновлять кэш.

Я запускаю задание cron каждую минуту. Я часто проверял ps и вижу ДВА экземпляра PHP, запускающих cron.php. Теперь это не нужно, потому что запуск одного экземпляра сделает все, что нужно. У меня есть другое задание, которое проверяет оперативную память, и иногда два экземпляра отключают его (я ожидаю, что большой объем оперативной памяти будет доступен в любое время, я могу уменьшить его, но не хочу). Я с трудом верю, что одно задание может занять больше минуты (хотя это может быть).

Как мне запустить задание, но не если процесс уже существует? Я не думаю, что сам код PHP может проверить, если он не подключается/не использует базу данных? Есть ли команда cron, которую я могу использовать? Я не хочу убивать экземпляр, если он >1 минуты. Просто не создавать новые.

решение1

Вот простое решение на основе скрипта bash; вы, вероятно, можете сделать то же самое в скрипте cron.php. Он на самом деле проверяет процессы, которые выполняются слишком долго; для автоматизированной системы это, вероятно, хорошая идея.

#!/bin/bash

# Exit if process is already running
if test -e /tmp/wordpress-job.pid; then
  # Check if the pid that was stored in /tmp/wordpress-job.pid does exist
  if ps ax -o pid= | grep $(cat /tmp/wordpress-job.pid ) &> /dev/null; then
    exit 0
  fi
fi

# Create the file that marks this process as running
echo $$ > /tmp/wordpress-job.pid

# Some extra security check to prevent the pid file
# to survive.
trap "rm -f /tmp/wordpress-job.pid" EXIT TERM INT HUP 

# Start the long-running process in the background
sleep 3600 & # long-running process

# Sleep some time before trying to kill that process
sleep 300

# Kill job if it takes longer than it should
kill %1

# Delete the file that marks this process as running
rm -f /tmp/wordpress-job.pid

Вам необходимо заменить «sleep 3600» на вашу командную строку php, а 300 ниже — на максимальное время, в течение которого может выполняться ваш скрипт.

решение2

Заставьте вашу запись crontab запустить это:

if mv /var/run/my-php-job.pending /var/run/my-php-job.running 2>/dev/null; then
  echo $$ >|/var/run/my-php-job.running   # optional
  … # run the job
  : >|/var/run/my-php-job.running         # optional
  mv /var/run/my-php-job.running /var/run/my-php-job.pending
fi

Поместите это в @rebootзапись crontab:

rm -f /var/run/my-php-job.running
touch /var/run/my-php-job.pending

Имя файла служит замком. Пока это .running, есть запущенное задание, и следующее задание не запустится. Когда это .pending, запущенное задание запускается и переключается на .running.

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

Если оболочка, выполняющая задание, аварийно завершается (что маловероятно и может произойти только в том случае, если кто-то намеренно завершит ее работу или в условиях нехватки памяти), файл блокировки застрянет на .running. (Если само задание аварийно завершается, это не проблема.) Вы можете обнаружить внезапную смерть предыдущего скрипта, но это значительно сложнее.

решение3

Существуют специальные утилиты для избежания параллельных запусков: flock в util-linux, lockf в системах BSD, shlock в NetBSD, а также в пакетах INN и cnews.

В наиболее вероятном случае (Linux) вызовите что-то похожее на:

flock -w 60 /somedir/lockfile cron.php

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

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

Связанный контент