отказоустойчивая crond замена

Оба comm столбец и первое слово args столбец в ps вывод показывает название исполняемой программы, если все вовлеченные следуют конвенции по умолчанию. Однако возможно иметь несоответствия по различным причинам.

Когда программа запускается, название команды как показано в args столбец выбран родительской программой, которая выполняет программу и передала как аргумент (argv[0]). Условно, родитель выбирает базовое имя исполняемого файла (т.е. путь к исполняемому файлу без части каталога), но это не осуществляется. После того как программа работает, она может перезаписать ту строку.

Init (по крайней мере, традиционный Linux SysVinit) перезаписывает argv[0] указать на текущий runlevel.

На Linux, comm столбец первоначально заполнен в ядром к первым 16 символам базового имени исполняемого файла. Процесс может изменить содержание с prctl системный вызов.

Если исполняемый файл переименован или удален, ни один comm столбец, ни args столбец отразит это.

ps не отображает путь к исполняемому файлу, это не находится в его должностной инструкции. lsof может сказать Вам с lsof -a -p 1 -d txt.

На Linux Вы видите эту информацию в файлах в /proc/PID/:

  • Имя процесса (comm поле) в в /proc/1/stat (второе поле в круглых скобках) и /proc/1/status (Name поле).
  • Путь к исполняемому файлу через /proc/1/exe.
  • Аргументы (запускающийся с argv[0]) в /proc/1/cmdline (аргументы разделяются пустыми байтами).

3
27.10.2014, 11:48
1 ответ

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

Если файл состояния существует и обновляется, то скрипт выходит.

Если этот файл является старым (I.e. Последнее написано накануне) или не существует сценарий, который работает, и в успешном прекращении записывается файл состояния.

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


/usr/local/bin/catchup.simple :

#! /usr/bin/env python

"""
first parameter is a path to a file /..../daily/some_name
That is a status/script file and the /daily/ indicates it needs to run at least
once a day (after reboot, after midnight).

The rest of the parameters is the command executed and its parameters.
If there are no more parameters beyond the first the actual status
file is /..../daily/some_name.status and is expected to be updated by calling
the /....daily/some_name script (which has to be executable). That
script doesn't need to know about the frequency and gets called with
the status file as first (and only) argument.

Valid directory names and their functioning:

   /daily/  run once a day (UTC)
   /hourly/ run once an hour

The actual scheduling and frequency to check if running is necessary, is
done using a crontab entry:

CU=/usr/local/bin/catchup.simple
CUD=/root/catchup

# month, hour, day_of_month, month day_of_week command
*/5 * * * * $CU $CUD/daily/getlogs curl ....

If mulitple days (or hours) have gone by, no runs are made for skipped
days.

If subprocess.check_output() fails the status file is not updated.
"""

import sys
import datetime
import subprocess

verbose = False  # set to True to debug

def main():
    if len(sys.argv) < 2:
        print 'not enough parameters for', sys.argv[0]
        return
    if len(sys.argv) == 2:
        status_file_name = sys.argv[1] + '.status'
        cmd = [sys.argv[1]]
    else:
        status_file_name = sys.argv[1]
        cmd = sys.argv[2:]

    freq = sys.argv[1].rsplit('/', 2)[-2]
    if verbose:
        print 'cmd', cmd
        print 'status', status_file_name
        print 'frequency', freq
    try:
        last_status = datetime.datetime.strptime(
            open(status_file_name).read().split('.')[0],
            "%Y-%m-%dT%H:%M:%S",
        )
    except (IOError, ValueError):
        last_status = datetime.datetime(2000, 1, 1)

    now = datetime.datetime.utcnow().replace(microsecond=0)
    if verbose:
        print last_status
        print 'now', now.isoformat()
    if freq == 'daily':
        if last_status.date() < now.date():
            subprocess.check_output(cmd)
        elif verbose:
            print 'already done today'
    elif freq == 'hourly':
        if last_status.date() < now.date() or \
           last_status.date() == now.date() and \
           last_status.hour < now.hour:
           subprocess.check_output(cmd)
        elif verbose:
            print 'already done this hour'

    with open(status_file_name, 'w') as fp:
        fp.write(now.isoformat())

if __name__ == "__main__":
    main()
2
27.01.2020, 21:27

Теги

Похожие вопросы