Run a command every “x seconds”

Relatively often I have to run some command every n seconds, to see what is happening.

To do this I generally resort to writing simple one liner in shell:

=$ while true; do some command; sleep 5; done

But it gets tedious. So I fixed it, by writing run_every.

You can run it as simply as:

=$ run_every 5s ls -l some_file
=$ ./run_every 5s ls -l some_file
2022-11-22 15:39:34 CET | Running, every 5s (since 2022-11-22 15:39:34 CET, so far 0s): ls -l some_file
ls: cannot access 'some_file': No such file or directory
2022-11-22 15:39:34 CET | Command ended with status: 2, sleeping for 5s
 
2022-11-22 15:39:39 CET | Running, every 5s (since 2022-11-22 15:39:34 CET, so far 5s): ls -l some_file
ls: cannot access 'some_file': No such file or directory
2022-11-22 15:39:39 CET | Command ended with status: 2, sleeping for 5s
 
2022-11-22 15:39:44 CET | Running, every 5s (since 2022-11-22 15:39:34 CET, so far 10s): ls -l some_file
-rw-r--r-- 1 depesz depesz 0 Nov 22 15:39 some_file
2022-11-22 15:39:44 CET | Command ended with status: 0, sleeping for 5s
...

There is some logic to detect that if you provided just one word as command, and it contains spaces, quotes, or pipe character, it will be called via shell:

=$ ./run_every 5s 'ls -l some_file'
2022-11-22 15:41:47 CET | Running, every 5s (since 2022-11-22 15:41:47 CET, so far 0s): /bin/bash -c ls\ -l\ some_file
-rw-r--r-- 1 depesz depesz 0 Nov 22 15:39 some_file
2022-11-22 15:41:47 CET | Command ended with status: 0, sleeping for 5s
...

Please note the header line showing bash -c ls\ -l\ some_file.

You can provide some options, all of which are shown in help page:

=$ ./run_every -h
Syntax:
    ... | run_every [options] -- RUN_EVERY command --options
 
Options:
    -d DATE_FORMAT : Format for displaying date format in header and footer.  Full command will be added at the end.  If it's set to
                     just - sign (-d-) header line will be skipped.
    -m MIN_SLEEP   : Minimal sleep to sleep between iterations (format like RUN_EVERY)
    -l             : Remove empty lines before header for next run.
    -h             : This help page
 
Defaults:
    -d '%Y-%m-%d %H:%M:%S %Z'
    -m '1s'
 
Notes:
 
RUN_EVERY is a number optionally suffixed by one of units:
 
    s - seconds, default
    m - minutes
    h - hours
    d - days
 
It has to be at least 1 second.
 
For example:
 
    run_every 12     command # Runs the command every 12 seconds
    run_every 2m     command # Runs the command every 2 minutes
    run_every 3h     command # Runs the command every 3 hours
    run_every 1d     command # Runs the command every 1 day
    run_every 1h 20m command # Runs the command every 1 hour, and 20 minutes"

Hope you'll find it useful.

3 thoughts on “Run a command every “x seconds””

  1. That’s what `watch` is pretty good at. I regularly list directories where I’m expecting a change, but it can even contains pipes and such (if quoted).

  2. I know about watch, but it just shows “current” state. Not all of them. For cases where I need just current state, I use watch. A lot.

Comments are closed.