Остановить задание, которое запускается снова

LinuxBeginner
Практиковаться сейчас

Введение

Обычно Status Desk обновляет небольшой кеш каждую минуту. Но неизвестный отправитель также посылает внутреннему сборщику синтетические учебные запросы. Остановка помогает лишь ненадолго: программа возвращается. Нужно убрать причину повторного запуска и сохранить штатное обновление статуса.

Достаточно базового владения терминалом. Status Server — разрешённая административная оболочка внутри целевого контейнера, открытая в /srv/status. Status Desk показывает настоящие счётчики сборщика. Оба контейнера разделяют ядро учебной инстанции. Все данные и запросы безвредны. Работа посвящена повторным запускам через cron, а не полному расследованию на рабочем сервере.

Наблюдение за возвращающейся программой

На этом шаге вы остановите работающую программу отправки и увидите, почему завершение одного экземпляра не устраняет причину.

Откройте Status Desk. refreshes — число успешных запросов обновления кеша; оно должно расти каждую минуту. uploads — число нежелательных учебных запросов, обычно по одному каждые пять секунд. История сохраняется после исправления. Перезагрузите страницу для получения текущих значений.

Перейдите в Status Server. Процесс — выполняющаяся программа. PID обозначает конкретный экземпляр, а путь и аргументы показывают его действия. ps выводит процессы. -e выбирает все, а -o задаёт столбцы: PID, родительский PID (PPID) и полную команду с аргументами.

ps -eo pid,ppid,args

Найдите /usr/bin/python3 /opt/status/uploader.py upload. Python — интерпретатор, /opt/status/uploader.py — файл программы, upload выбирает учебную операцию отправки. Соседний процесс flock удерживает блокировку, не позволяющую cron одновременно создавать несколько копий. Программу обновления кеша не трогайте.

Сигнал — запрос процессу. TERM просит нормально завершить работу. Следующий pkill выбирает всю командную строку через -f; ^ и $ в шаблоне в кавычках обозначают её начало и конец. Поэтому команда затрагивает именно этот Python-процесс, а не родителя или вашу оболочку. Выполните один раз:

pkill -TERM -f '^/usr/bin/python3 /opt/status/uploader.py upload$'

Отсутствие вывода нормально. Если совпадений нет, снова посмотрите процессы, не расширяя шаблон на все программы Python. Дайте процессу секунду для завершения и повторите просмотр:

sleep 1
ps -eo pid,ppid,args

Отправитель Python должен исчезнуть. Проверка подтверждает завершение исходного экземпляра, но не полную очистку сервера.

sleep ждёт указанное число секунд. Подождите 80 секунд, чтобы пересечь хотя бы одну настоящую границу минуты, и снова выведите процессы:

sleep 80
ps -eo pid,ppid,args

Тот же путь с аргументом upload должен вернуться с новым PID. Теперь в цепочке родителей есть CRON — процесс запуска заданий планировщика. Новый PID означает новый запуск, а не другое исходное задание. Если нагрузка задержала выполнение, подождите ещё 20 секунд и повторите просмотр. Перезагрузите Status Desk: отправки возобновятся, штатные обновления также продолжатся. Нужно выяснить, что запускает программу.

Поиск и отключение повторного запуска

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

Cron — демон, то есть фоновая служба, запускающая команды по расписанию. Пользовательская crontab содержит задания одной учётной записи. Этот терминал работает от root внутри учебного контейнера, поэтому crontab -l показывает задания целевого аккаунта. Учётная запись платформы не затрагивается.

crontab -l

Вы должны увидеть:

* * * * * /usr/bin/flock -n /run/uploader.lock /usr/bin/python3 /opt/status/uploader.py upload

Первые пять полей: минута, час, день месяца, месяц и день недели. * означает любое значение; * * * * * запускает каждую минуту. Далее идёт команда. flock -n получает блокировку без ожидания: если её уже держит другой отправитель, повторный вызов завершается. Цель совпадает с остановленным процессом.

Системные задания также находятся в /etc/cron.d/. ls перечисляет файлы, cat показывает содержимое небольшого файла. * после каталога разворачивается в его файлы.

ls /etc/cron.d
cat /etc/cron.d/*

Файл status-cache содержит:

* * * * * root /usr/bin/python3 /opt/status/cache-refresh.py refresh

В отличие от пользовательской crontab, системный файл cron содержит аккаунт, здесь root, между пятью полями времени и командой. Эта разрешённая команда обновляет Status Desk. Одинаковая частота сама по себе не делает задание неразрешённым. Другие служебные записи, установленные пакетами, можно оставить.

Для аккуратного редактирования сначала скопируйте пользовательское расписание в рабочий текстовый файл. > записывает список в файл, заменяя старую копию. Сделайте это один раз до редактирования: повторная команда затрёт черновик.

crontab -l > /srv/status/root.cron

nano открывает текстовый редактор. В начало строки отправителя добавьте #. Cron игнорирует комментарии, начинающиеся с #. Сохраните текст для восстановления и не меняйте другие записи.

nano /srv/status/root.cron

Стрелками перейдите в начало строки, введите #, нажмите Ctrl+O, Enter для сохранения и Ctrl+X для выхода. Установите изменённый файл, передав его путь команде crontab:

crontab /srv/status/root.cron
crontab -l

Строка отправителя должна начинаться с #. Cron автоматически перечитывает изменения, перезапуск не нужен. Комментария в рабочей копии недостаточно до её установки. Если изменили не ту строку, откройте черновик, восстановите её и установите файл снова. Текущий отправитель может продолжать работу: удаление расписания не завершает уже запущенный процесс.

Завершение работающей копии и проверка восстановления

На этом шаге вы закончите очистку и сравните нежелательную активность с рабочей функцией за полный интервал расписания.

Остановите текущий Python-отправитель тем же точным шаблоном:

pkill -TERM -f '^/usr/bin/python3 /opt/status/uploader.py upload$'

Если его уже нет, завершение без совпадения ожидаемо; продолжайте. Дайте процессу секунду для завершения:

sleep 1

curl отправляет сетевой запрос. -sS скрывает индикатор прогресса, но показывает ошибки. URL указывает на внутренний контейнер сборщика, доступный из Status Server. /state возвращает текущие счётчики и временные метки Unix последних запросов.

curl -sS http://collector:8080/state

Запомните uploads, refreshes и last_refresh, затем дайте настоящему cron поработать:

sleep 80
curl -sS http://collector:8080/state

uploads должен остаться прежним, а refreshes и last_refresh — увеличиться. После перезагрузки Status Desk показывает те же факты. Старые отправки остаются свидетельствами; обнуление счётчика скрывает историю, не устраняя повторный запуск.

Ещё раз выведите процессы:

ps -eo pid,ppid,args

cron -f должен оставаться: -f удерживает демон контейнера на переднем плане. Отправитель должен по-прежнему отсутствовать. Проверка независимо наблюдает ещё 80 секунд, поэтому оценивание занимает около 90 секунд. Она только читает конфигурацию и текущее состояние.

Если отправки растут, проверьте оба расположения cron и установку закомментированной пользовательской crontab. Если обновления остановились, восстановите разрешённую запись status-cache. Не останавливайте cron и не удаляйте все задания, чтобы скрыть симптом: служба статуса от них зависит. Исправление удаляет показанный механизм cron, но не доказывает отсутствие всех возможных способов закрепления на настоящем сервере.

Резюме

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