1

I wanna use watch on certain commands and files (e.g. w), having it run in the background and notify me of any change. I've tried the following:

(watch -g cat tmp && echo "changed") &

However, nothing happens when I change the contents of tmp and watch only exits on change when I foreground it with fg.

Is there a way to have watch running in the background and notify me of a change?

  • 3
    this is not what watch is for. watch is for repeatedly running the same command and displaying its output. you probably want to either pipe the output of tail tmp into, e.g., an awk script that exits on the first new line, or use inotify to monitor changes in a file. – cas Jun 23 '21 at 06:02

2 Answers2

2

A simple way would be via inotifywait in -monitor mode, i.e. running permanently instead of exiting after the first recorded event. Specify an -event like file/directory modification to watch - or do not to show all events like, opening, accessing, writing etc.. See man inotifywait for more about possible events.

$inotifywait -m -e modify tmp &
$echo 1 >> tmp
tmp MODIFY

The drawback is that in this version you do not execute a command on your own, but merely get the standard notification. For explicitly executing a command and idefinitely watching the file/directory, something like this would work (using -quiet mode):

while ((1)) ; do \
   inotifywait -q -e modify tmp && echo "tmp was changed" \
done &
FelixJN
  • 13,566
1

watch is not designed for what you want to do.

At some point watch tries to reconfigure the terminal. Being in the background it gets SIGTTOU and stops. The whole job gets SIGTTOU.

In an interactive shell with job control you can see this when you invoke jobs afterwards. In zsh you would see a note suspended (tty output). jobs in other shells may not be so informative.

In my tests I needed to redirect stdout and stderr away from the terminal:

(watch -g cat tmp >/dev/null 2>&1 && echo "changed") &

If the original settings of the terminal include tostop then echo will trigger SIGTTOU when it tries to write. Run stty -tostop beforehand to make sure the settings allow echo to print to the terminal:

stty -tostop; (watch -g cat tmp >/dev/null 2>&1 && echo "changed") &

Note other processes may configure the terminal on their own, therefore they may interfere.