Unix trick of the week: cron + time + swap stdin/stderr + logger

peter's picture

This week I was trying to get some timing data from a process that was being run out of cron. Being lazy, and not wanting to rewrite the process itself, I decided to try getting the elapsed time directly from the cron entry.

The original cron entry was:


* * * * * /home/peter/test.sh >/dev/null

The final entry is

* * * * * /usr/bin/time -f \%E /home/peter/test.sh 2>&1 1>/dev/null | logger -p local6.debug

Now for some dissection:


* * * * *
Run this every minute


/usr/bin/time -f \%E /some/path/script.sh
Time the command and only report the elapsed time. The bash shell has a built-in 'time' command, but I prefer the formatting of GNU time. In a regular shell script the format string would just be %E, but the '%' in a cron script means 'newline' unless you escape it with a '\' (backslash)


2>&1 1>/dev/null
Send stderr (filehandle 2) to stdout (filehandle 1), send stdout (filehandle 1, initially) to /dev/null.


| logger -p local6.debug
Pipe the stdout (the elapsed time) into logger for logging into syslog. You'd also need to add a line like this to /etc/syslogd.conf:


local6.debug /var/log/test.log
and send a 'kill -HUP' to your syslog daemon.

On the way to putting this together I came across the following little idiom that I'd used before but long forgotten. To swap standard input and standard output entirely, use:


/some/command.sh 3>&2 2>&1 1>&3-
Now for me to explain this would take me away too long from other work that must be done. Maybe later....

Comments

Justin Miller's picture

/some/command.sh 3>&2 2>&1 1>&3-

Oh, now that's cool. It's like a little shell game (no pun intended).