Як автоматично запустити скрипт, коли вміст каталогу зміниться в Linux?


17

Я хочу автоматично запускати сценарій, коли нові файли копіюються в певний каталог. Іншими словами, чи є в Linux спосіб "переглянути" каталог за змінами, а потім виконати щось у відповідь на зміни?


Це обговорення було проведено на кожному stackexchange сайті;) см superuser.com/questions/181517 / ... stackoverflow.com/questions/4380527 / ... і т.д.
masterxilo

Відповіді:


17

Якщо вам пощастить , достатньо , щоб бути на розподілі DEBiAN на основі apt-get install dnotify. Інші дистрибутиви, мабуть, мають щось подібне - шукайте dnotifyназву.

dnotify - це проста програма на основі API ядра Linux 2.4.19 +. dnotify може виконувати задану команду щоразу, коли зміст конкретного каталогу змінюється. Він запускається з командного рядка і приймає два аргументи: один або декілька каталогів для моніторингу та команду для виконання, коли каталог змінюється. Параметри керують, які події слід викликати: коли файл читався в каталозі, коли створювався, видалявся тощо.

Якщо ви хочете вирішити це у власній програмі, позначте також API, який ви хочете використовувати.


4
@MikeB, після того, як ви запропонували Гуглінг запропонувати вам, я замість цього застосував inotify, який, очевидно, перевершує його. Дякую, що вказали мені на правильний напрямок. apt-get install inotify-tools
GeneQ

7
@GeneQ, inotify замінив dnotify.
Девід

1
Так само і в Gentoo:emerge inotify-tools
James Sneeringer

Так, я збирався сказати, ядро ​​2.4.19 є деяким давнім ;-) інотифікувати - це шлях.
David Z

О так ... я забув, що було останнім часом :)
MikeyB

12

Ви можете запустити сценарій за допомогою інструментів inotify, подібного до цього. Він буде спостерігати за каталогом щодо змін у модифікованих файлах, нових файлах та видалених файлах, потім виконає сценарій.

#!/bin/sh
while inotifywait -e modify -e create -e delete /home/me/code; do
    rsync [options] /home/me/code/ /media/nfs/code/ 
done

Просто врахуйте, що якщо каталог джерела змінюється під час його копіювання, inotifywait НЕ буде його бачити, і ці зміни не будуть скопійовані до подальших змін, коли копія закінчиться. Напевно, це не проблема.
Рауль Салінас-Монтеагудо

Як можна запустити це в демон-режимі?
Кріс Ф

4

Думаю, інкрон - це в основному те, що ти хочеш. Він використовує inotify як механізм сповіщення (який, як зазначали інші, перевищує dnotify), але не потребує сценарію, який постійно працює, використовуючи inotifywait або подібне (хоча, очевидно, демон інкон працює весь час). Загальносистемні "crontabs" та "crontabs" користувачів підтримуються аналогічно стандартним cron, але замість того, щоб вказати час як тригери, використовуються ініціативні події та назви файлів / каталогів.

Вважаю, що інкрон упакований для багатьох дистрибутивів, включаючи Ubuntu та Debian, я вважаю.


0

Існує програмне забезпечення виключно для цієї мети, autoenv Ви можете перевірити це.


0

entr - це найпростіший та найкомпонентніший інструмент сповіщення файлів, який я бачив. Його використання оптимізоване для перегляду файлів, а не каталогів, але це також може вирішити вашу справу.

Для виявлення та дії над доданим файлом комбінуйте його з іншими інструментами, наприклад, наприклад make. entrне надсилає ім'я чи щось подібне, він просто виконує те, що ви йому сказали, щоб запустити.

Щоб перевірити наявність доданих файлів у каталозі:

## entr exits with rc=0 when terminated
## rc=1 when watched files go away or don't exist to begin with
## rc=2 when new files arrive in watched directories
until echo /path/to/directory_to_watch | entr -d do_stuff
do sleep 1; done

Якщо ви також хочете діяти, коли існуючий файл змінюється:

## Here's why it comes in handy that entr exits when new files are added --
## find gets re-run.
until find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/* |
    entr -d do_stuff
do sleep 1; done

... і ось тут стає в нагоді механізм циклу, оскільки findвираз запуститься знову, якщо буде доданий файл.

Якщо ви хочете покращити обробку помилок і хочете переконатися, що все працює лише один раз за доданий / видалений файл, вони стають трохи химерними, але для цих простих випадків це геніально.


EDIT: Якщо ви хочете зробити це на системному рівні, щось на зразок incron , просто додайте скрипт до улюбленого менеджера процесів (наприклад, s6 , runit , systemd або sysvinit і пропустіть цикл:

#!/bin/bash
exec entr -d do_stuff < <(find /path/to/directory_to_watch/ -path /path/to/directory_to_watch/*)

execІ заміна процесу ( <(...)) мають важливе значення при роботі з менеджером процесу, для обробки сигналів належним чином (тобто , щоб отримати оболонку з шляху).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.