Как обрабатывать новые файлы для обработки в работе cron
Как я могу проверить файлы, которые я уже обработал в сценарии, чтобы не обрабатывать их снова? и / или что не так с тем, как я делаю это сейчас?
Здравствуйте, я запускаю tshark с опцией кольцевого буфера для выгрузки в файлы через 5 МБ или 1 час. Я написал скрипт на Python для чтения этих файлов в формате XML и выгрузки в базу данных, это прекрасно работает.
Моя проблема в том, что это действительно интенсивный процесс, один из этих 5 МБ может превратиться в файл размером 200 МБ при преобразовании в XML, поэтому я не хочу выполнять какую-либо ненужную обработку.
Скрипт запускается каждые 10 минут и обрабатывает ~5 файлов за цикл, так как сканирует папку, в которой создаются файлы для любых новых записей, я записываю хэш файла в базу данных и при следующем запуске проверяю хэш, и если это не в базе данных я сканирую файл. Проблема заключается в том, что это не работает каждый раз, а заканчивается обработкой файлов, которые он уже сделал. Когда я проверяю хеш файла, который он пытается обработать, он не отображается нигде в базе данных, поэтому и пытаюсь обрабатывать его снова и снова.
Я печатаю имя файла + хэш в выводе скрипта:
используя файл /var/ss01/SS01_00086_20100107100828.cap с хешем: 982d664b574b84d6a8a5093889454e59 используя файл /var/ss02/SS02_00053_20100106125828.cap с хешем: 8caceb6af7328c4aed2ea349062b74e9 используя файл /var/ss02/SS02_00075_20100106184519.cap с хешем: 1b664b2e900d56ca9750d27ed1ec28fc используя файл /var/ss02/SS02_00098_20100107104437.cap с хешем: e0d7f5b004016febe707e9823f339fce используя файл /var/ss02/SS02_00095_20100105132356.cap с хешем: 41a3938150ec8e2d48ae9498c79a8d0c используя файл /var/ss02/SS02_00097_20100107103332.cap с хешем: 4e08b6926c87f5967484add22a76f220 используя файл /var/ss02/SS02_00090_20100105122531.cap с хешем: 470b378ee5a2f4a14ca28330c2009f56 используя файл /var/ss03/SS03_00089_20100107104530.cap с хешем: 468a01753a97a6a5dfa60418064574cc используя файл /var/ss03/SS03_00086_20100105122537.cap с хешем: 1fb8641f10f733384de01e94926e0853 используя файл /var/ss03/SS03_00090_20100107105832.cap с хешем: d6209e65348029c3d211d1715301b9f8 используя файл /var/ss03/SS03_00088_20100107103248.cap с хешем: 56a26b4e84b853e1f2128c831628c65e используя файл /var/ss03/SS03_00072_20100105093543.cap с хешем: dca18deb04b7c08e206a3b6f62262465 используя файл /var/ss03/SS03_00050_20100106140218.cap с хешем: 36761e3f67017c626563601eaf68a133 используя файл /var/ss04/SS04_00010_20100105105912.cap с хешем: 5188dc70616fa2971d57d4bfe029ec46 используя файл /var/ss04/SS04_00071_20100107094806.cap с хешем: ab72eaddd9f368e01f9a57471ccead1a используя файл /var/ss04/SS04_00072_20100107100234.cap с хешем: 79dea347b04a05753cb4ff3576883494 используя файл /var/ss04/SS04_00070_20100107093350.cap с хешем: 535920197129176c4d7a9891c71e0243 используя файл /var/ss04/SS04_00067_20100107084826.cap с хешем: 64a88ecc1253e67d49e3cb68febb2e25 используя файл /var/ss04/SS04_00042_20100106144048.cap с хешем: bb9bfa773f3bf94fd3af2514395d8d9e используя файл /var/ss04/SS04_00007_20100105101951.cap с хешем: d949e673f6138af2d388884f4a6b0f08
Единственные файлы, которые он должен делать, - это один на папку, поэтому всего 4 файла. Это вызывает ненужную обработку, и мне приходится иметь дело с перекрывающимися заданиями cron + другие службы были затронуты.
То, что я надеюсь получить из этого поста, является лучшим способом сделать это, или, надеюсь, кто-то может сказать мне, почему это происходит, я знаю, что последний может быть сложным, поскольку это может быть множество причин.
Вот код (я не кодер, но администратор системы, так что будьте добры:P), строка 30-32 обрабатывает сравнения хешей. Заранее спасибо.
5 ответов
Хороший способ обрабатывать / обрабатывать файлы, созданные в случайное время, - это использоватьincron
скорее, чем cron
, (Примечание: поскольку incron использует системные вызовы inotify ядра Linux, это решение работает только с Linux.)
В то время как cron
работает на основе дат и времени, incron
запускает задание на основе изменений в отслеживаемом каталоге. Например, вы можете настроить incron для запуска задания каждый раз при создании или изменении нового файла.
На Ubuntu пакет называется incron
, Я не уверен насчет RedHat, но я считаю, что это правильный пакет: http://rpmfind.net//linux/RPM/dag/redhat/el5/i386/incron-0.5.9-1.el5.rf.i386.html.
После установки пакета incron прочитайте
man 5 incrontab
для получения информации о том, как настроить файл конфигурации incrontab. Ваш incron_config
файл может выглядеть примерно так:
/var/ss01/ IN_CLOSE_WRITE /path/to/processing/script.py $#
/var/ss02/ IN_CLOSE_WRITE /path/to/processing/script.py $#
/var/ss03/ IN_CLOSE_WRITE /path/to/processing/script.py $#
/var/ss04/ IN_CLOSE_WRITE /path/to/processing/script.py $#
Затем, чтобы зарегистрировать этот конфиг с помощью демона incrond, вы должны запустить
incrontab /path/to/incron_config
Это все, что нужно сделать. Теперь, когда файл создается в /var/ss01, /var/ss02, /var/ss03 или /var/ss04, команда
/path/to/processing/script.py $#
выполняется с заменой $# на имя только что созданного файла.
Это избавит от необходимости хранить / сравнивать хэши, и файлы будут обрабатываться только один раз - сразу после их создания.
Просто убедитесь, что ваш сценарий обработки не записывает в верхний уровень отслеживаемых каталогов. Если это произойдет, то incrond заметит созданный новый файл и снова запустит script.py, отправив вас в бесконечный цикл.
incrond отслеживает отдельные каталоги и не осуществляет рекурсивный мониторинг подкаталогов. Таким образом, вы можете указать tshark записать в /var/ss01/tobeprocessed, использовать incron для мониторинга / var / ss01 / tobeprocessed и сделать так, чтобы ваш script.py записывал в / var / ss01, например.
PS. Существует также интерфейс Python для inotify, называемый pyinotify. В отличие от incron, pyinotify может рекурсивно отслеживать подкаталоги. Однако в вашем случае я не думаю, что функция рекурсивного мониторинга полезна или необходима.
Я недостаточно знаю, что находится в этих файлах, так что это может не сработать для вас, но если у вас есть только один предполагаемый потребитель, я бы рекомендовал использовать каталоги и перемещать файлы, чтобы отразить их состояние. В частности, вы можете иметь структуру dir, такую как
/waiting
/progress
/done
и использовать относительную атомарность mv
изменить "состояние" каждого файла. (Будь то mv
я считаю, что это действительно атомарно, зависит от вашей файловой системы.)
Когда ваша задача обработки хочет работать с файлом, она перемещает его из waiting
в progress
(и следит за тем, чтобы движение прошло успешно). Таким образом, никакое другое задание не может поднять его, так как оно больше не ждет. Когда файл завершен, он перемещается из progress
в done
где задача очистки может удалить или архивировать старые файлы, которые больше не нужны.
Почему бы просто не переместить обработанный файл в другой каталог?
Вы упомянули перекрывающиеся рабочие места cron. Означает ли это, что один процесс преобразования может начаться до завершения предыдущего? Это означает, что вы будете выполнять движение в начале преобразования. Если вы беспокоитесь о прерванном преобразовании, используйте промежуточный каталог и перейдите в последний каталог после завершения.
Я вижу несколько вопросов.
Если у вас есть перекрывающиеся задания cron, вам нужен механизм блокировки для контроля доступа. Разрешить только один процесс за раз, чтобы устранить проблему перекрытия. Вы можете настроить скрипт оболочки для этого. Создайте "блокировку", создав каталог (атомарный mkdir), обработайте данные, затем удалите каталог блокировки. Если сценарий оболочки обнаруживает, что каталог уже существует, когда он пытается его создать, то вы знаете, что другая копия уже запущена, и он может просто выйти.
Если вы не можете изменить таблицы (таблицы) cron, просто переименуйте исполняемый файл и назовите свой сценарий оболочки так же, как старый исполняемый файл.
Хеш-функции не гарантируют, что они являются уникальными идентификаторами файлов, скорее всего, они есть, но это не является абсолютно гарантированным.
Если я правильно читаю код, вы обновляете базу данных (я имею в виду журнал обработанных файлов) в самом конце. Поэтому, когда у вас есть огромный файл, который обрабатывается и еще не завершен, другая работа cron будет "законно" работать над ним. - оба успешно завершены, в результате чего две записи в базе данных.
Я предлагаю вам переместиться вверх по журналу к базе данных, который будет действовать как блокировка для последующих cron jobs и с "успехом" или "выполнением" в самом конце. Последняя часть важна, поскольку то, что показано как обработка, но не имеет завершенного состояния (в сочетании с понятием времени), может быть программно завершено как ошибка. (То есть, cron job пытался обработать его, но никогда не завершал его, и обработка журнала показа в течение 1 недели!)
Подвести итоги
- Переместите журнал в базу данных, чтобы он действовал как замок
- Добавьте состояние "успешно" или "завершено", которое дало бы понятие состояния с ошибкой
PS: Не поймите это неправильно, но код немного сложен для понимания. Я не уверен, делаю ли я вообще.