-1

What I'd like to have: Running a command y with watch command and have watch command update only as soon as output of command y has changed.

Imagine a bash script with 3 lines of echo output

Hello world!
Hello universe!
Aloha multiverse!

I want the bash script to be watched, but updates only should happen, if said output has changed due to editing of the script and saving it afterwards, so, modification date.

I fear, that watch command as usual, updating every 2 seconds by default, when being run multiple hours daily, will run down storage disk life time too fast. I mean, just imagine how many read/write operations just that command produces. I feel like this is so wasteful. It would be much better, if watch command just sleeps, and the act of saving the watched command wakes watch up, running the script once again and then sleeps again.

What I mean is: The automatic equivalent of doing that handwork we all know: 1. Writing on a script, 2. then saving it, 3. then executing it once again to see if the saved changes work out as intended - repeat. I mean for seeing the change, we don't execute the command every 2 seconds, but only once, event-based.

Is the price of automating that tedious evergoing switch between writing a script and executing it unavoidable evergoing interval update wearing down storage disk life by exessive growth of read and write processes?

A compromise could be to highen the interval time by -n option, for example up to every 30 seconds, but can't watch command somehow do any better?

I mean, I've already thought of maybe letting watch exit by -g option as soon as the file changed, but that doesn't change a thing at watch causing read operations every 2 seconds or other interval until the change has happened, keeping the storage disk busy all the time.

And while loops have the same problem, don't they? Or could this be the solution: Kind of rebuilding watch command with a while loop, making it truely event-based somehow (?), and so minimizing the amount of read and write operations while developing a script?

This is about efficiency, minimalism, saving ressources as much as possible.

  • "every two seconds" is … practically never for a modern PC (this isn't 1969!), especially if you're running an editor in the meantime; interactive programs typically create a lot of files very quickly, and write small changes to disk much more often (leave alone browsers or graphical frontends!). Is there any indication this is actually a problem that needs solving? – Marcus Müller Jan 22 '24 at 17:49
  • You're not really saving any resources here. You going on the internet and asking about this would have wasted more Joule and more disk wear than this could ever safe in a lifetime. You're really barking up the wrong tree. Think about this: almost certainly something updates your screen – 60 times per second. You're worrying about a watch command that might change something that is updated anyways twice per second. – Marcus Müller Jan 22 '24 at 17:51
  • ... and on most modern file systems (and certainly ZFS) will not even hit the disc, even when there was a change. But I can agree with the OP that it's still consuming CPU cycles, hogging memory buffers, etc. It would just be more parsimonious if the mechanism were event-based. And someone else must've thought that too when they came up with the inode notification kernel subsystem. :-) – zwets Jan 22 '24 at 18:12
  • I don't understand how reducing the screen updates of watch reduces disk wear. A few dots are not connected here. Are we talking about running a command which has side effects that write to storage, and monitoring its output? Such that if that command's source code has not changed, there won't be any interesting change in its output? – Kaz Jan 23 '24 at 02:04

1 Answers1

1

Instead of using watch, use inotifywait. This is built against the Linux inode notify kernel subsystem, which provides an event-based API to observe file system changes.

On Ubuntu, the inotify-tools package provides inotifywait, as well as various other small tools that operate either on files, directories, or whole file systems.

So, you could do (in bash):

while true; do 
    diff <(./watchee) <(inotifywait -qqe modify ./watchee; ./watchee)
done

Or, using watch (mind the quoted semicolon):

watch inotifywait -qqe modify ./watchee';' ./watchee

And hope that watch won't spawn a bunch of commands to catch up with missed intervals - as the BUGS section in its manpage suggests could happen in certain circumstances.

zwets
  • 296