Watchman – A File and Directory Watching Tool for Changes

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/
Watch a Directory in Linux
Watch a Directory in Linux

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
Create a Trigger on Directory
Create a Trigger on Directory

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 
View Watch List
View Watch List

To view the trigger list for a root, run the following command (replace ~/bin with the root name).

$ watchman trigger-list ~/bin
Show Trigger List for a Root
Show Trigger List for a Root

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
Test Watchman Configuration
Test Watchman Configuration

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.

  1. Swatchdog – Simple Log File Watcher in Real-Time in Linux
  2. 4 Ways to Watch or Monitor Log Files in Real Time
  3. fswatch – Monitors Files and Directory Changes in Linux
  4. Pyintify – Monitor Filesystem Changes in Real Time in Linux
  5. 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.

Hey TecMint readers,

Exciting news! Every month, our top blog commenters will have the chance to win fantastic rewards, like free Linux eBooks such as RHCE, RHCSA, LFCS, Learn Linux, and Awk, each worth $20!

Learn more about the contest and stand a chance to win by sharing your thoughts below!

Aaron Kili
Aaron Kili is a Linux and F.O.S.S enthusiast, an upcoming Linux SysAdmin, web developer, and currently a content creator for TecMint who loves working with computers and strongly believes in sharing knowledge.

Each tutorial at TecMint is created by a team of experienced Linux system administrators so that it meets our high-quality standards.

Join the TecMint Weekly Newsletter (More Than 156,129 Linux Enthusiasts Have Subscribed)
Was this article helpful? Please add a comment or buy me a coffee to show your appreciation.

8 Comments

Leave a Reply
  1. ———– On RHEL/CentOS ———–

    # yum install autoconf automake python-setuptools python-devel libssl-devel libtool 
    # yum groupinstall 'Development Tools' 
    

    you need to add “openssl-devel” for certain redhat. Else will hit below error when execute ‘make‘:-

      CXX      thirdparty/jansson/libwmanjson_a-strbuffer.o
      CXX      thirdparty/jansson/libwmanjson_a-strconv.o
      CXX      thirdparty/jansson/libwmanjson_a-utf.o
      CXX      thirdparty/jansson/libwmanjson_a-value.o
      AR       libwmanjson.a
      CXX      watchman-ChildProcess.o
      CXX      watchman-ContentHash.o
    ContentHash.cpp:13:25: fatal error: openssl/sha.h: No such file or directory
     #include 
                             ^
    compilation terminated.
    make[1]: *** [watchman-ContentHash.o] Error 1
    make[1]: Leaving directory `/vagrant_data/watchman_build.2017-09-08T22:41:55Z/watchman'
    make: *** [all] Error 2
    
    Reply
  2. 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.

    Reply
      • 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/

        Reply

Got Something to Say? Join the Discussion...

Thank you for taking the time to share your thoughts with us. We appreciate your decision to leave a comment and value your contribution to the discussion. It's important to note that we moderate all comments in accordance with our comment policy to ensure a respectful and constructive conversation.

Rest assured that your email address will remain private and will not be published or shared with anyone. We prioritize the privacy and security of our users.