14

Does watch only monitor the visible output of a command? Say I'm in a directory with the following contents:

$ ls a b c d e f g h i j k l m n 

If I run watch -g ls -1 I expect it to exit if a file is added or removed. What actually happens is that it exits only if the file in question is visible in the terminal output of watch:

$ watch -g ls -1 Every 2.0s: ls -1 Wed Nov 13 16:35:03 2013 a b c d e f 

Deleting the file m, which is not visible because of the size of my terminal, does nothing. Deleting a visible file, say d, causes watch to exit as expected.

The -g flag is explained thusly in my man page:

 -g, --chgexit Exit when the output of command changes. 

What's going on? Is this normal? How can I use watch for commands with long output? I am using watch from procps-ng 3.3.4 which was installed from the Debian repos.

2
  • What does the -g option to watch do? I don't find it in my version of watch Commented Nov 13, 2013 at 16:09
  • @1_CR see updated question, it should cause it to exit when the output changes. It does work as advertised when the change is visible on the screen. Commented Nov 13, 2013 at 16:18

2 Answers 2

11

I found this thread titled: Bug#225549: have watch monitor stderr. That thread is from 2008, but it looks like older versions don't support the watching of anything other than STDOUT.

So we're limited to just STDOUT. As for visible there is a lot of language in the info watch and man watch that make me think your observation/assumption is correct.

excerpt

 watch runs command repeatedly, displaying its output (the first screen‐ full). This allows you to watch the program output change over time. By default, the program is run every 2 seconds; use -n or --interval to specify a different interval. 

Also this bit under BUGS:

BUGS Upon terminal resize, the screen will not be correctly repainted until the next scheduled update. All --differences highlighting is lost on that update as well. 

If I had to guess I'd think they were storing the visible bits in a buffer between runs, and then analyzing just those characters.

EDIT #1

I debugged this further using strace and you can see watch reading the output from the ls command so it's internally dropping the change.

before I delete the m file

$ strace -o w.log watch -g 'ls -1' read(3, "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\nw.lo"..., 4096) = 34 close(3) = 0 --- SIGCHLD (Child exited) @ 0 (0) --- munmap(0x7f4da83af000, 4096) = 0 wait4(31011, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 31011 rt_sigaction(SIGTSTP, {SIG_IGN, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, {0x7f4da7f81ee0, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, 8) = 0 write(1, "\33[H\33[2JEvery 2.0s: ls -1\33[1;140H"..., 119) = 119 rt_sigaction(SIGTSTP, {0x7f4da7f81ee0, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, NULL, 8) = 0 nanosleep({2, 0}, NULL) = 0 stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0 pipe([3, 4]) = 0 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f4da839f9d0) = 31014 close(4) = 0 fcntl(3, F_GETFL) = 0 (flags O_RDONLY) fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4da83af000 lseek(3, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) read(3, "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\nw.lo"..., 4096) = 34 close(3) = 0 munmap(0x7f4da83af000, 4096) = 0 --- SIGCHLD (Child exited) @ 0 (0) --- 

after the m file is deleted

--- SIGCHLD (Child exited) @ 0 (0) --- rt_sigaction(SIGTSTP, {SIG_IGN, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, {0x7f4da7f81ee0, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, 8) = 0 poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) poll([{fd=0, events=POLLIN}], 1, 0) = 0 (Timeout) write(1, "\33[1;158H8\33[11;163H", 18) = 18 rt_sigaction(SIGTSTP, {0x7f4da7f81ee0, [], SA_RESTORER|SA_RESTART, 0x7f4da79b94a0}, NULL, 8) = 0 nanosleep({2, 0}, NULL) = 0 stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=3519, ...}) = 0 pipe([3, 4]) = 0 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f4da839f9d0) = 31028 close(4) = 0 fcntl(3, F_GETFL) = 0 (flags O_RDONLY) fstat(3, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f4da83af000 lseek(3, 0, SEEK_CUR) = -1 ESPIPE (Illegal seek) read(3, "a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nn\nw.log\n", 4096) = 32 close(3) = 0 --- SIGCHLD (Child exited) @ 0 (0) --- munmap(0x7f4da83af000, 4096) = 0 wait4(31028, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 31028 
3
  • Yeah, it just seems weird, it makes it impossible to run something like watch -g foo; echo "Something changed!". It seems a strangely crippling bug in such an established program. Commented Nov 14, 2013 at 1:50
  • @terdon - my ancient version of Fedora didn't have the -g switch but I tried it on Ubuntu and it behaves the same. Commented Nov 14, 2013 at 2:19
  • OK, that's really weird then. So it does actually monitor and see the change, it just doesn't react to it! Definitely a bug then. Commented Nov 14, 2013 at 12:15
2

I expect it to exit if a file is added or removed

I'm pretty sure you're after inotify-tools.

My manpage for watch, from procps-ng, says

watch runs command repeatedly, displaying its output and errors (the first screenfull).

10
  • That's not what he's asking about, he's trying to understand the behavior of an update occurring, being displayed via STDOUT, but isn't visible in the terminal b/c he's re-sized it so that the output that is being changed is "off screen". Most everyone I've discussed this with today would've expected watch to behave as the OP, and exit with the change. Commented Nov 14, 2013 at 7:06
  • Yes we've already discussed that too, I highlighted that same text in my answer. I know Terdon fairly well and at this point he wants to know the reason why. Commented Nov 14, 2013 at 7:32
  • I agree it's not the answer to his question, but it's the solution to his problem. Commented Nov 14, 2013 at 7:33
  • You mean using inotify? That's not what he's after, he wants to know why watch behaves this way. He knows about inotify. Commented Nov 14, 2013 at 7:34
  • That's his question. What he's trying to do with it is what I quoted: wait for a file to be added or removed. Watch isn't the tool for that job. Commented Nov 14, 2013 at 7:36

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.