Linux'ta bir dizinin içeriği değiştiğinde otomatik olarak bir komut dosyası nasıl çalıştırılır?


17

Yeni dosyalar belirli bir dizine kopyalandığında otomatik olarak bir komut dosyası çalıştırmak istiyorum. Başka bir deyişle, Linux'ta değişiklikler için bir dizini "izlemenin" ve ardından değişikliğe yanıt olarak bir şeyin çalıştırılmasının bir yolu var mı?


Bu tartışma, her
yığın değiş tokuş

Yanıtlar:


17

Debian tabanlı bir dağıtım için yeterince şanslıysanız apt-get install dnotify,. Diğer dağıtımların muhtemelen benzer bir şeyleri vardır - dnotifyadı arayın .

dnotify Linux çekirdeği 2.4.19 + 'ın dnotify API'sine dayanan basit bir programdır. dnotify, belirli bir dizinin içeriği her değiştiğinde belirtilen bir komutu yürütebilir. Komut satırından çalıştırılır ve iki bağımsız değişken alır: izlemek için bir veya daha fazla dizin ve dizin her değiştiğinde yürütülecek komut. Seçenekler hangi olayların tetikleneceğini kontrol eder: bir dosya dizinde ne zaman okunduğunu, ne zaman oluşturulduğunu, silindiğini vs.

Bunu kendi programınızda ele almak istiyorsanız, dnotify da kullanmak istediğiniz API'dir.


4
@MikeB, Google'ın önerdiğini bildirmeden sonra, görünüşe göre onu aşan inotify kullandım. Bana doğru yönü gösterdiğin için teşekkürler. apt-get install
inotify

7
@GeneQ, inotify yerini dnotify aldı.
David

1
Aynı şekilde Gentoo:emerge inotify-tools
James Sneeringer

Evet, söyleyecektim, çekirdek 2.4.19 biraz eski ;-) inotify gitmek için bir yol.
David Z

Oh evet ... Hangisi daha yeni olduğunu unuttum :)
MikeyB

12

İnotify araçlarıyla böyle bir komut dosyası çalıştırabilirsiniz. Değiştirilmiş dosyalar, yeni dosyalar ve silinen dosyalardaki değişiklikleri izlemek için dizini izler, ardından komut dosyasını yürütür.

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

Sadece kaynak dizini kopyalanırken değişirse, inotifywait dizinin bunu görmeyeceğini ve kopya tamamlandıktan sonra başka değişikliklere kadar bu değişikliklerin kopyalanmayacağını göz önünde bulundurun. Muhtemelen bir sorun değil.
Raúl Salinas-Monteagudo

Bunu daemon modunda nasıl çalıştırabilirsiniz?
Chris F

4

incron temelde istediğin şey bence. İnotify'ı bildirim mekanizması olarak kullanır (ki diğerlerinin de belirttiği gibi supercedes dnotify), ancak inotifywait veya benzeri kullanarak sürekli çalışan bir komut dosyası gerektirmez (açıkçası, incron daemon her zaman çalışıyor olsa da). Sistem genelinde 'crontabs' ve kullanıcı 'crontabs', standart cron'a benzer şekilde desteklenir, ancak süreleri tetikleyici olarak belirtmek yerine inotify olayları ve dosyalar / dizin adları kullanılır.

incron, Ubuntu ve Debian da dahil olmak üzere birçok dağıtım için paketlenmiş olduğuna inanıyorum.



0

entr gördüğüm en basit ve en birleştirilebilir dosya bildirim aracıdır. Kullanımı dizinlerden ziyade dosyaları izlemek için optimize edilmiştir, ancak vakanızı da çözebilir.

Eklenen dosyayı algılamak ve üzerinde işlem yapmak için, örneğin, örneğin make. entradı veya bunun gibi bir şey göndermez, sadece çalıştırmasını söylediğiniz şeyi çalıştırır.

Bir dizine eklenen dosyaları kontrol etmek için:

## 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

Varolan bir dosya değiştiğinde de işlem yapmak istiyorsanız:

## 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

... ve findbir dosya eklendiğinde ifade tekrar çalışacağı için döngü mekanizması bu noktada işe yarar.

Daha iyi hata işleme istiyorsanız ve eklenen / kaldırılan dosya başına yalnızca bir kez çalıştığından emin olmak istiyorsanız, işler biraz tuhaflaşır, ancak bu basit durumlar için mükemmeldir.


DÜZENLEME: Bir sistem düzeyinde bunu yapmak istiyorsanız, böyle bir şey incron , tıpkı (favori süreç yöneticisi komut dosyası eklemek S6 , runit , systemd veya sysvinit ve döngü atlamak:

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

Ve execve işlem ikamesi ( <(...)), bir işlem yöneticisinden çalıştırılırken, sinyalin düzgün şekilde işlenmesi (yani kabuğun yoldan çekilmesi) için önemlidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.