Posted on 8 Comments

Fab tool: watch

A post by Ronald reminded me I wanted to write about watch. The Linux watch command is a fab tool, it allows you to run a program at a set interval, such as every 5 seconds. Handy for keeping an eye on stuff!

Update 2009-06-30: yesterday I wrote “… watch does not re-load and run the program, but goes in and resets the program counter.” (and was un-recommending it for use on production systems for that reason). I was blindly quoting an otherwise trusted source, and it was wholly wrong. Numerous people had a peek at the source code (all the way back to 1997) and found the popen(). So, I stand corrected and my apologies for not doing extra homework in the first place before posting! (I’m leaving the comments as they are)

Posted on 8 Comments

8 thoughts on “Fab tool: watch

  1. > That is, until you learn how it works. It does not re-load and run the program, oh no it’s much smarter than that: it goes in and resets the program counter. That’s right, it literally pokes into its child process!

    Where did you get that? Looking at the source, it uses nothing more than popen/pclose to run a child program:
    http://procps.cvs.sourceforge.net/viewvc/procps/procps/watch.c?revision=1.16&view=markup

    Indeed, if you check the process list while watch is running, you can see the pids of the child processes incrementing with each run. There’s nothing suspicious here, and certainly no poking around the program counters.

  2. If you have a ‘some … kernel bug’, you have other problems than watch causing a segfault in the watched program… If all it does is using official interfaces, this is not different than using a debugger, etc. I have seen more database errors than watch errors, watch doesn’t seem to be that problematic.

    I actually downloaded an read watch.c (from procps 3.2.7-9ubuntu2.1) to see how it works, if there are script interpreters, dynamic loading and initialization of global variables involved. In line 264 you have:

    if (!(p = popen(command, “r”))) {
    perror(“popen”);
    do_exit(2);
    }

    Very hacky indeed 🙂 Which (maybe prehistoric?) version of watch is you information about?

  3. Arjen,
    care to share the evidence on your claim? Looking at watch source code, I could only see a “getc” on the child process pointer (created by popen). Where did you get the “poke” stuff?

    Giuseppe

  4. I have no idea what version of watch you have been looking at, but the one from procps (on SourceForge) restarts the process after it terminates.

  5. Hi Arjen,

    I’m sorry, but unless you’re talking about a different ‘watch’ than the one that ships with, well probably every Linux out there, you’re just wrong. Where did you get this idea? You didn’t provide any reference whatsoever.

    http://procps.cvs.sourceforge.net/viewvc/procps/procps/watch.c?view=markup

    You can see quite clearly that it calls p = popen(…) … getc(p) … pclose(p)

    Compare the file available at the above URL to the one available in your operating system of choice. (Compared and matched to CentOS’s myself.)

    Regards,

    Jeremy

  6. Looking at the source it does a popen() pclose() for each iteration. I don’t see any poking in the version from:

    cvs -d :pserver:anoncvs@sources.redhat.com:/cvs/procps co procps

    The man page also says it’s just passed to a shell.

  7. I’m not quite sure where you got that idea from, but watch(1) uses popen(3) so it execs a new process every time.

  8. I wonder where you got it from. It sounded so unbelievable that I took the time to download the source of watch.c and look inside.

    Indeed, no crazy program counter manipulations. Pretty ordinary stuff – popen(), getc() until eof, pclose(), wait, repeat. Nothing too fancy.

Comments are closed.