Вопрос или проблема
У меня проблема в приложении на PHP, где некоторые процессы, похоже, работают несколько дней – я все еще пытаюсь разобраться, как и почему это происходит, но в то время как это происходит, ресурсы сервера истощаются, и нагрузка резко увеличивается. Затем я вручную вхожу и убиваю процессы, и все в порядке, пока это не повторится.
Поэтому, как временное решение, я хочу запустить cron для удаления всех php процессов старше, скажем, 1 часа.
Когда я получаю список процессов, он показывает мне следующее (я удалил все, что не относится к делу):
2049 7204994 php-fpm: master process (/etc/php-fpm.conf)
42146 42087 php-fpm: pool www -DFOREGROUND
47118 49511 php-fpm: pool www
47119 49511 php-fpm: pool www
47162 47222 php-fpm: pool www -- uid 0 -- gid 0 -- logger=files
47280 39490 php-fpm: pool www
51993 12066 php-fpm: pool www
51994 12066 php-fpm: pool www
53634 8575 php-fpm: pool www
53749 2590 php-fpm: pool www
53775 766 php-fpm: pool www
53780 447 php-fpm: pool www
53781 358 php-fpm: pool www
53784 111 php-fpm: pool www
53797 26 php-fpm: pool www
53799 0 ps -eo pid,etimes,cmd
Я хочу иметь возможность убивать любые процессы старше 3600 секунд, НО не включая мастер-процесс или процессы с дополнительными аргументами.
Если я попробую
ps -eo pid,etimes,cmd | awk '$2 > 3600 && $3 == "php-fpm: pool www"'
то ничего не возвращается.
Если я попробую
ps -eo pid,etimes,cmd | awk -v pat="php-fpm" '$2 > 3600 && $3 ~ pat'
это возвращает мне все вышеупомянутое, что я не хочу, так как не хочу убивать мастер-процесс, но если я попробую
ps -eo pid,etimes,cmd | awk -v pat="php-fpm: pool" '$2 > 3600 && $3 ~ pat'
ИЛИ
ps -eo pid,etimes,cmd | awk -v pat="pool" '$2 > 3600 && $3 ~ pat'
то я не получаю ничего в ответ.
Как я могу сделать так, чтобы это возвращало только те процессы, в которых шаблон точно соответствует “php-fpm: pool www” и ничего другое?
Ответ или решение
Чтобы решить вашу задачу по завершению процессов PHP, работающих более одной минуте, вы можете использовать команду ps
вместе с awk
и kill
. Следующий скрипт будет проверять время выполнения процессов и завершать те, которые превышают 3600 секунд, исключая главный процесс PHP-FPM и процессы с дополнительными аргументами.
Вот шаги, которые вы можете выполнить:
- Откройте терминал на вашем сервере.
- Создайте новый файл скрипта, например
kill_long_php_processes.sh
.
#!/bin/bash
# Получаем список процессов и обрабатываем его
ps -eo pid,etimes,cmd | awk '
{
# Преобразуем время выполнения в секунды
split($2, a, ":");
etime = a[1] * 3600 + a[2] * 60 + a[3]; // Время в секундах
# Фильтруем процессы
if (etime > 3600 && $3 == "php-fpm:" && $4 == "pool" && $5 == "www") {
print $1; # Вернем только PID
}
}' | xargs -r kill -9
- Сохраните файл и сделайте его исполняемым:
chmod +x kill_long_php_processes.sh
- Добавьте этот скрипт в cron для автоматического выполнения. Для редактирования crontab используйте команду:
crontab -e
Добавьте следующую строку, чтобы запускать скрипт каждый час:
0 * * * * /путь/к/вашему/скрипту/kill_long_php_processes.sh
Замените /путь/к/вашему/скрипту/
на актуальный путь к вашему файлу.
Объяснение:
-
ps -eo pid,etimes,cmd
: Эта команда выводит все процессы с их PID, временем выполнения и командой, которую они запускают. -
awk
: Используется для обработки выводаps
. Мы разбиваем строку с временем выполнения на части (часы, минуты, секунды), преобразуем их в общее количество секунд и проверяем, превышает ли оно 3600 секунд. -
if (etime > 3600 && $3 == "php-fpm:" && $4 == "pool" && $5 == "www")
: Это условие фильтрует процессы, чтобы выбрать только те, которые соответствуют вашему критерию. -
xargs -r kill -9
: Командаxargs
получает список PID и отправляет их командеkill
, чтобы завершить процессы.
С помощью этого скрипта вы сможете автоматически завершать процессы PHP, которые работают дольше часа, и, тем самым, поддерживать стабильность работы вашего сервера.