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