I'm trying to write a BASH script with the purpose of using watch command to monitor a local git repository for changes from the remote branch and then executing a task.

Let's say the script is called task.sh and looks like:

watch -n 3000 (git remote update && git status) | \
grep -i "your branch is behind origin/" && \ 
{ "pull changes, run tests, etc." ; }

What I have posted is more or less what I have thus far, but I can't seem to get the last part to work. In other words, it doesn't seem to pick up when I have a made a change to the git branch. I was able to redirect the output from watch to a file like this watch -n 3000 ls 1>> file.txt , but using this method would require opening the file which I think is slow and error prone.

I basically want watch to continuously run until I kill the script that started it, although if there's a better method than watch that would be fine too.

  • 1
    Uh.. cron looks like a much better foreman for this particular job.
    – DopeGhoti
    Commented May 3, 2017 at 22:41
  • @DopeGhoti I was hoping that my script would be simpler and would give me a little more control but that hasn't been the case.
    – zachaz35
    Commented May 3, 2017 at 22:51

1 Answer 1


As DopeGhoti mentioned, cron would be a much better choice for this.

Your example already has a 50 minute interval. If making the interval an hour is acceptable, many modern distros have an /etc/cron.hourly directory. Anything in that directory with the executable bit set will be run hourly (most implementations I've seen use run-parts which runs the executables in that directory linearly by filename).

If a shorter interval is a must, I'd recommend /etc/cron.d. The cron daemon generally parses this directory directly, so there is no need for the executable bit to be set. You could create a file called task with the following contents.

*/30 * * * * root /path/to/task.sh

The first 5 fields are for minute, hour, day of the month, month, and day of the week. In this case we're giving minute a step value of 30 minutes. So, this particular example will run task.sh every 30 minutes, every hour, every day of the month, every... you get the idea.

Step values over 30 minutes in the minutes field lead to execution at N minutes past the hour, where N is the value in the minutes field.

See here for one solution to odd intervals.

Now on to the bash code...

The reason this isn't working as expected is because grep never returns an exit value to be evaluated by &&. It's still greping the output of watch.

This can be seen in the following example. The echo and sleep within the curly braces take the place of watch. After the sleep exits, grep can too. The second date doesn't run until after grep exits and the exit code can be evaluated.

[vagrant@localhost ~]$ date +%s; { echo a; sleep 15; } | grep 'a' && date +%s

One way to correct this would be to move everything to be within watch.

watch -n 15 'bash -c "echo a | grep 'a' && date +%s"'

Another option is use a while-true-loop.

[vagrant@localhost ~]$ while :; do echo a | grep 'a' && date +%s; sleep 15; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .