« Previous 1 2 3 Next »
Look for file changes and kick off actions with Watchman
On Guard
Excluding Files
When you define a trigger, you can specify files to exclude; that is, you can prevent the trigger from executing if a file name contains a particular pattern. Note that with rsync, such an exclusion will not be taken in account. The following command can be performed at run time, and the configuration will be updated accordingly:
watchman -- trigger /opt/repos 'repos-sync' \ -X '*.css' \ -I '*' -- /usr/local/sbin/sync.sh
The -X
excludes a pattern and -I
includes a pattern. For a full accounting of pattern syntax, please refer to the Watchman website [4].
When a new file or any change inside the watched directory is detected, Watchman waits for the filesystem (the directory) to be idle for a time before dispatching triggers. By default, this time is 20 milliseconds, and this option is named "settle"
. To increase the amount of time, you must set the "settle"
option in the global configuration file – /etc/watchman.json
by default. This file uses JSON syntax, as well:
{ "settle": 60 }
The settle option is useful if you want to prevent the script from executing before a large file write has completed.
Real-Time Virus Scanner
Watching a real-time virus scanner, such as the free antivirus ClamAV [5] or the free anti-malware tool Linux Malware Detect (a.k.a., maldet
) [6], would be another interesting use case for Watchman. The maldet tool uses the Linux inotify
facility to perform real-time scanning; however, Solaris/Illumos do not have inotify, so you would be unable to use this functionality on such operating systems. In this case, a good solution would be to use Watchman.
For example, suppose you want to scan files for viruses with the clamscan
utility. Whenever a file is added, changed, or deleted, the Watchman service will trigger the scanner.sh
script (Listing 4), which invokes the virus scanner, passing in the file name to the $@
variable.
Listing 4
scanner.sh
01 #!/bin/bash 02 03 for file in $@ 04 do 05 clamscan --stdout --no-summary --infected ${WATCHMAN_ROOT}/$file 06 EL=$? 07 if [ $EL -eq 1 ] 08 then 09 # Virus found 10 echo "Virus found: ${WATCHMAN_ROOT}/$file" | \ mailx -s "Virus found" mail@example.com 11 elif [ $EL -eq 2 ] 12 then 13 # Clamscan error 14 echo "Scan error: ${WATCHMAN_ROOT}/$file" | \ mailx -s "Scan error" mail@example.com 15 fi 16 # Else no virus found 17 done
However, when you delete a file, Watchman still kicks the trigger, and the name of the deleted file is passed to your script, even though you don't need to scan a non-existent file; therefore, you need to use extended trigger syntax
(Listing 5). The key options are "exists"
and "append_files": true
. The append_files
entry enables the arguments – that is, the list of new or changed files – to be passed to the script, and "exists"
tells Watchman to trigger the action only if the file exists.
Now, if you execute
watchman watch /opt/share
Watchman passes a list of changed, but not deleted, files to the script, using the relative path to "root" (/opt/share
). Of course, you could also use clamdscan
, if the clamd service is up and running, or the aforementioned maldet tool on Linux.
Listing 5
Extended Trigger Syntax
01 watchman -j <<-EOT 02 ["trigger", "/opt/share", { 03 "name": "scanner", 04 "expression": ["allof", ["match", "*"], ["exists"]], 05 "command": ["/usr/local/sbin/scanner.sh"], 06 "append_files": true 07 }] 08 EOT
Shutdown and Reboot
The correct way to shut down Watchman is:
watchman shutdown-server
Remember that if you reboot your server, you need a way to start Watchman automatically at bootup. For SmartOS [7], you can import a sample SMF manifest from the watchman-pkgsrc
GitHub site [8] (check the paths). For CentOS 7 with the systemd suite, you can create the file /etc/systemd/system/watchman.service
containing something like Listing 6. Finally, you need to issue
systemctl enable watchman systemctl start watchman
to enable Watchman on bootup and start the service.
Listing 6
watchman.service
01 [Unit] 02 Description=Watchman 03 After=network.target 04 05 [Service] 06 Type=simple 07 User=root 08 ExecStart=/usr/local/bin/watchman --log-level 1 watch-list -f 09 ExecStop=/usr/local/bin/watchman shutdown-server 10 11 [Install] 12 WantedBy=multi-user.target
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy ADMIN Magazine
Subscribe to our ADMIN Newsletters
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Most Popular
Support Our Work
ADMIN content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.