Назад | Перейти на главную страницу

Найти (и убить) старые процессы

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

В идеале хотелось бы найти что-то подобное, но для процессов.

Система - это Debian linux, и он будет написан и запущен cron, поэтому у меня нет серьезных проблем с чем-то большим, но понятным.

Вы можете сделать это с помощью комбинации ps, awk и kill:

ps -eo pid,etime,comm

Дает вам вывод в трех столбцах, с PID процесса, прошедшим с момента запуска процесса временем и именем команды без аргументов. Прошедшее время выглядит следующим образом:

mm:ss
hh:mm:ss
d-hh:mm:ss

Поскольку вам нужны процессы, которые выполняются более недели, вы должны искать строки, соответствующие этому третьему шаблону. Вы можете использовать awk для фильтрации процессов по времени выполнения и по имени команды, например:

ps -eo pid,etime,comm | awk '$2~/^7-/ && $3~/mycommand/ { print $1 }'

который напечатает pid всех команд, соответствующих mycommand, которые выполнялись более 7 дней. Вставьте этот список в kill, и все готово:

ps -eo pid,etime,comm | awk '$2~/^7-/ && $3~/mycommand/ { print $1 }' | kill -9

killall --quiet --older-than 1w process_name

Всю необходимую информацию можно получить из ps -ef. См. Столбец «STIME». Совместите это с grep чтобы отсортировать нужные вам процессы. В этот момент вы можете использовать cut чтобы получить pid всех подходящих процессов и передать их kill.

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

если вы root, чтобы избавиться от мусора (/ proc / fs proc / stat ...)

find /proc -maxdepth 1 -regex '/proc/[0-9]*' -type d -mtime +2 -exec basename {} \;

Никто не упомянул пс-наблюдатель Вот. Я думаю, вы могли бы сравнить $ start_time с помощью функции elapsed2sec, но я не совсем уверен. Вот моя первая мысль:

[myproc]
occurs = every
trigger = elapsed2secs('$start_time') > 7*DAYS
action = <<EOT
  echo "$command has been running more than 7 days" | /bin/mail user\@host
  kill -TERM $pid
EOT

Не знаю, работает ли это, но это должно быть хорошей отправной точкой.

Если у вас есть сценарий Python / Perl / Ruby, который вы хотите убить, killall не поможет тебе с тех пор killall будет просто искать «python» или «perl», он не может совпадать с именем конкретного скрипта.

Чтобы убить все процессы старше X секунд, где любая часть полной запущенной команды соответствует строке, вы можете запустить это как root:

MAX_SECONDS=43200
PROGRAM_THAT_NEEDS_TO_DIE=bad-python-script.py
ps -eo pid,etimes \
    | grep -v PID \
    | awk '$2>'$MAX_SECONDS'{ print $1 }' \
    | xargs --no-run-if-empty ps -f --pid \
    | grep $PROGRAM_THAT_NEEDS_TO_DIE \
    | awk '{ print $2 }' \
    | xargs --no-run-if-empty kill -9

Использовать ps чтобы получить список всех процессов (-e) и вывести только pid и прошедшее количество секунд (-o pid,etimes).

grep -v PID чтобы удалить строку заголовка.

Использовать awk чтобы выбрать только строки, в которых прошедшие секунды больше 43200 с (12 часов), и вырезать только первый столбец с PID.

Передайте список PID обратно в ps чтобы получить полный список процессов.

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

Использовать awk снова вытащить PID скрипта.

Если есть какие-то процессы, убейте их.

Когда процесс запускается, он создает каталог в файловой системе / proc. Вы можете использовать команду find, чтобы получить каталоги старше 7 дней и убить процессы следующим образом:

find /proc -user myuser -maxdepth 1 -type d -mtime +7 -exec basename {} \; | xargs kill -9