最後更新: 2019-08-07
介紹
* trigger commands when a file or directory event occurs
* incrond 不支援 Recursive directory
目錄
Install
# C6, C7: epel
yum install incron
獲得 program:
- incrond
- incrontab
Config:
/etc/incron.conf
Enable & Start Service
# C7
systemctl enable incrond --now
# C6
chkconfig incrond on
service incrond start
設定檔
/etc/incron.conf
# examined by incrond for system table files system_table_dir = /etc/incron.d # examined by incrond for user table files user_table_dir = /var/spool/incron # contains users allowed to use incron allowed_users = /etc/incron/allow
incrontab
incrontab - a table manipulator for the incron system.
Help:
man incrontab
Permission
If /etc/incron.allow exists only users listed here may use incron
Otherwise if /etc/incron.deny exists only users NOT listed here may use incron
If none of these files exists everyone is allowed to use incron.
# Allow root only
echo root > /etc/incron.allow
Syntax
incrontab [-u user] [-f config] [-l | -r | -e | -t | -d]
CMD
# list
incrontab -l
# edit (/var/spool/incron/<USERNAME>)
incrontab -e
# Reloading the current table by incrond
incrontab --reload
requesting table reload for user 'root'... request done
It is done through "touching" the table. This feature is for creating watches on newly created files (/var/spool/incron/FILE)
# List of supported event types(mask) (delimited by commas)
incrontab -t
IN_ACCESS ... IN_CLOSE_WRITE(8) # File opened for writing was closed IN_CLOSE_NOWRITE # File or directory not opened for writing was closed ... IN_MOVED_TO ... IN_DELETE IN_DELETE_SELF IN_CLOSE ...
incrontab 的 Format
Syntax
<path> <mask> <command>
path: an absolute filesystem path ( the same path may occur only once per table )
mask: an event mask (in symbolic or numeric form)
Path
* Path 不支援 *.txt 之類 (/root/test_folder/*.txt)
mask
- IN_ACCESS
- ...
- IN_CLOSE_WRITE
- ...
WILDCARDS
- $$ dollar sign
- $@ watched filesystem path
- $# event-related file name
- $% event flags (textually)
- $& event flags (numerically)
Logging Event Script
Usage:
incrontab -l
/root/test_folder IN_ALL_EVENTS /root/scripts/mon.sh "$@ $# $& $%"
cat /root/scripts/mon.sh
#!/bin/bash
# 這裡的 "$@" 不是 incrond 的 "$@", 是 bash 的 "$@"
echo "$@" >> /tmp/log.txt
Create File (>>, >, touch) 時有的 event
echo "test" >> test.txt # 它們是一樣的 Event
echo "test" > test.txt
"/root/test_folder test.txt 8 IN_CLOSE_WRITE"
"/root/test_folder test.txt 256 IN_CREATE"
"/root/test_folder test.txt 32 IN_OPEN"
"/root/test_folder test.txt 2 IN_MODIFY"
touch test.txt
"/root/test_folder test.txt 8 IN_CLOSE_WRITE"
"/root/test_folder test.txt 256 IN_CREATE"
"/root/test_folder test.txt 32 IN_OPEN"
"/root/test_folder test.txt 4 IN_ATTRIB"
Append File(>>)
echo "test" >> test.txt
"/root/test_folder test2.txt 32 IN_OPEN"
"/root/test_folder test2.txt 2 IN_MODIFY"
"/root/test_folder test2.txt 8 IN_CLOSE_WRITE"
結論:
所有 create file 都有 IN_CLOSE_WRITE event
Delete File
"/root/test_folder test2.txt 512 IN_DELETE"
Move
# move in
"/root/test_folder test.txt 128 IN_MOVED_TO"
# move out
"/root/test_folder test.txt 64 IN_MOVED_FROM"
Read
cat test.txt
"/root/test_folder test.txt 32 IN_OPEN"
"/root/test_folder test.txt 16 IN_CLOSE_NOWRITE"
List
ls
"/root/test_folder 1073741856 IN_OPEN,IN_ISDIR" "/root/test_folder 1073741840 IN_CLOSE_NOWRITE,IN_ISDIR"
Example
# it will include hidden directories in the observation
/home IN_CREATE,dotdirs=true /usr/local/bin/abcd $#
# it will exclude sub-directories from the observation
/home IN_CREATE,recursive=false /usr/local/bin/abcd $#
Tips
1) 建議 mon Folder, 不要 mon File
vim FILE ":w" 係只能觸發一次 EVENT,
因為佢係 replace file 的 !! (.mySecRules.conf.swp -> mySecRules.conf)
replace 後 mon 就斷了, 因為 FILE 的 Inode 變了 (stat FILE)
應用: Reload apache when update modsecurity rules
incrontab -l
/etc/httpd/modsecurity.d IN_CLOSE_WRITE /root/scripts/modsecurity_reload.sh "$#"
modsecurity_reload.sh
#!/bin/bash Log=/tmp/log.txt if [ "$1" == "mySecRules.conf" ]; then echo `date` > $Log apachectl -t &>> $Log if [ $? -eq 0 ]; then service httpd reload fi fi
Notes
# 觀察有無 reload
tail -f /var/log/httpd/error_log
應用: 利用 incron 行 git
incrontab -l
/home/vhosts/datahunter.org/realtime.txt IN_CLOSE_WRITE /home/vhosts/datahunter.org/scripts/realtime_git-it.sh
realtime_git-it.sh
#!/bin/bash _trigger_file=/home/vhosts/datahunter.org/realtime.txt _log=/var/log/git_log/realtime.log _git_path=/home/vhosts/datahunter.org/public_html _email='[email protected]' # git setting export HOME="/root" # locking _scriptname=$(basename $0) _pidfile="/var/run/$_scriptname.pid" exec 200>$_pidfile flock -xn 200 || { echo -n "another instance is running"; exit 1; } _pid=$$ echo $_pid echo $_pid 1>&200 # code if [ -s $_trigger_file ]; then echo "cleanup trigger_file & git" echo "$@" >> $_log # cleanup _msg=`cat $_trigger_file | tr '\n' ' ' | tr -d '\r'` echo -n "" > $_trigger_file # git cd $_git_path echo `date` >> $_log git add . >> $_log 2>&1 git commit -m "$_msg" >> $_log 2>&1 git config --file /root/.gitconfig credential.helper store >> $_log 2>&1 git push >> $_log 2>&1 # log file echo "=============================================" >> $_log # e-mail notification echo "git time: `date`" | mail -s'notification - server git' $_email fi # clean lock rm -f $_lock
FAQ
IN_MODIFY 與 IN_CLOSE_WRITE
Why do inotify events fire more than once (IN_MODIFY)
when writing large files it would fire more than once.
That sounded fair
The IN_MODIFY event is emitted on a file content change (e.g. via the write() syscall)
while IN_CLOSE_WRITE occurs on closing the changed file.
It means each change operation causes one IN_MODIFY event
(it may occur many times during manipulations with an open file)
whereas IN_CLOSE_WRITE is emitted only once (on closing the file).
參考: http://datahunter.org/lock