Watchman is an open source and cross-platform file watching service that watches files and records or performs actions when they change. It is developed by Facebook and runs on Linux, OS X, FreeBSD, and Solaris. It runs in a client-server model and employs the inotify utility of the Linux kernel to provide a more powerful notification.
Useful Concepts of Watchman
- It recursively watches watch one or more directory trees.
- Each watched directory is called a root.
- It can be configured via the command-line or a configuration file written in JSON format.
- It records changes to log files.
- Supports subscription to file changes that occur in a root.
- Allows you to query a root for file changes since you last checked, or the current state of the tree.
- It can watch an entire project.
In this article, we will explain how to install and use watchman to watch (monitor) files and record when they change in Linux. We will also briefly demonstrate how to watch a directory and invoke a script when it changes.
Installing Watchman File Watching Service in Linux
We will install watchman service from sources, so first install these required dependencies libssl-dev, autoconf, automake libtool, setuptools, python-devel and libfolly using following command on your Linux distribution.
----------- On Debian/Ubuntu ----------- $ sudo apt install autoconf automake build-essential python-setuptools python-dev libssl-dev libtool ----------- On RHEL/CentOS ----------- # yum install autoconf automake python-setuptools python-devel openssl-devel libssl-devel libtool # yum groupinstall 'Development Tools' ----------- On Fedora ----------- $ sudo dnf install autoconf automake python-setuptools openssl-devel libssl-devel libtool $ sudo dnf groupinstall 'Development Tools'
Once required dependencies installed, you can start building watchman by downloading its github repository, move into the local repository, configure, build and install it using following commands.
$ git clone https://github.com/facebook/watchman.git $ cd watchman $ git checkout v4.9.0 $ ./autogen.sh $ ./configure $ make $ sudo make install
Watching Files and Directories with Watchman in Linux
Watchman can be configured in two ways: (1) via the command-line while the daemon is running in background or (2) via a configuration file written in JSON format.
To watch a directory (e.g ~/bin
) for changes, run the following command.
$ watchman watch ~/bin/
The following command writes a configuration file called state
under /usr/local/var/run/watchman/<username>-state/, in JSON format as well as a log file called log
in the same location.
You can view the two files using the cat command as show.
$ cat /usr/local/var/run/watchman/aaronkilik-state/state $ cat /usr/local/var/run/watchman/aaronkilik-state/log
You can also define what action to trigger when a directory being watched for changes. For example in the following command, ‘test-trigger
‘ is the name of the trigger and ~bin/pav.sh
is the script that will be invoked when changes are detected in the directory being monitored.
For test purposes, the pav.sh
script simply creates a file with a timestamp (i.e file.$time.txt
) within the same directory where the script is stored.
time=`date +%Y-%m-%d.%H:%M:%S` touch file.$time.txt
Save the file and make the script executable as shown.
$ chmod +x ~/bin/pav.sh
To launch the trigger, run the following command.
$ watchman -- trigger ~/bin 'test-trigger' -- ~/bin/pav.sh
When you execute watchman to keep an eye on a directory, its added to the watch list and to view it, run the following command.
$ watchman watch-list
To view the trigger list for a root, run the following command (replace ~/bin
with the root
name).
$ watchman trigger-list ~/bin
Based on the above configuration, each time the ~/bin
directory changes, a file such as file.2019-03-13.23:14:17.txt
is created inside it and you can view them using ls command.
$ ls
Uninstalling Watchman Service in Linux
If you want to uninstall watchman, move into the source directory and run the following commands:
$ sudo make uninstall $ cd '/usr/local/bin' && rm -f watchman $ cd '/usr/local/share/doc/watchman-4.9.0 ' && rm -f README.markdown
For more information, visit the Watchman Github repository: https://github.com/facebook/watchman.
You might also like to read these following related articles.
- Swatchdog – Simple Log File Watcher in Real-Time in Linux
- 4 Ways to Watch or Monitor Log Files in Real Time
- fswatch – Monitors Files and Directory Changes in Linux
- Pyintify – Monitor Filesystem Changes in Real Time in Linux
- Inav – Watch Apache Logs in Real Time in Linux
Watchman is an open source file watching service that watches files and records, or triggers actions, when they change. Use the feedback form below to ask questions or share your thoughts with us.
———– On RHEL/CentOS ———–
you need to add “openssl-devel” for certain redhat. Else will hit below error when execute ‘make‘:-
@BK,
Thanks for the tip, specified openssl-devel to the required packages…
Any examples of trigger scripts?
I am thinking if you want to capture which file(s) changed and what the changes were, you could star with a mirror folder of the folder you have watchman watching.
On a change, do a dry run of rsync to get a list of what changed, and also archive those files to an archive folder using a timestamp extension.
Then do a live rsync to make the mirror folder match the one being watched.
Just trying to get ideas as to how to make watchman give you a history of what changed and what the changes were.
@Mike
Thanks for sharing your thoughts with us. We are grateful.
Watchman is now also available in Debian and Ubuntu and can be installed via ‘apt-get install watchman‘.
@Anuradha
Many thanks for sharing this. We are grateful.
Surely! Here is what I am going to use as the trigger script, the folders can be whatever you need:
#!/usr/bin/bash
SOURCE=/root/lookatme
MIRROR=/root/mirrors/lookatme
ARCHIVE=/root/archives/lookatme
TIMESTAMP=`date +%Y-%m-%d.%H:%M:%S`
cd $SOURCE
RUNNING=`ps -ef | grep rsync | grep -v grep`
RESULT=$?
if [ $RESULT == 0 ];
then
exit;
fi
for item in `rsync -a --out-format="%n" --dry-run $SOURCE/ $MIRROR/ | grep -E '[[:alnum:]]' | grep -v .*.swp`
do
if [ -f $item ];
then
save=`echo $item | sed s#/#%#g`
cp $item $ARCHIVE/$save.$TIMESTAMP
fi
done
rsync -a $SOURCE/ $MIRROR/
@Mike
Wonderful! Many thanks for sharing.