Another self-explanatory bash hack. This one was developed to limit the total run time of a test script, where one of the commands was hanging but I was trying to chase down a different bug.
#!/bin/bash # Run code with a time limit. This is trickier than you'd think, because the alarm # signal (or any other) won't be delivered to the parent until any foreground task # completes. That kind of defeats the purpose here, since a hung task will also # block the signal we're using to un-hang it. Fortunately, a directed "wait" gives # us a way to work around this issue. We start both the alarm task and the task # that does real work in the background, then either way we get into exit_handler # and kill whichever one's still running. It's a little bit inconvenient that # everything has to be wrapped in a "main" function to work, but there's a lot about # bash that's unfortunate. TIME_LIMIT=5 function exit_handler { if [ -n "$ALREADY_EXITING" ]; then return fi if [ -n "$WATCHER" ]; then echo "killing watcher" kill -s SIGKILL $WATCHER fi if [ -n "$WORKER" ]; then echo "killing worker" kill -s SIGKILL $WORKER fi echo "time to die" } trap exit_handler EXIT function alrm_handler { echo "alarm went off" unset WATCHER exit } trap alrm_handler ALRM export PARENT_PID=$$ (sleep $TIME_LIMIT; echo "ring ring"; kill -s SIGALRM $PARENT_PID) & export WATCHER=$! # Example function to demonstrate different completion sequences. function main { if [ "$1" != 0 ]; then echo "sleeping" sleep $1 echo "waking up" fi } main "$@" & export WORKER=$! wait $WORKER unset WORKER # Test with shorter sleep times to see the worker finish normally, with longer # sleep times to see the watcher cut things short. |
man timeout (if you have coreutils installed)
Not quite the same thing, Jason. Timeout is great if you just want to run a single command under a time limit, but it doesn’t handle more complex needs like running a whole series of commands and attaching a trap function to the timer expiration and not having to deal with even more variable-scope issues (enough of a pain in bash already). Having multiple solutions for multiple problems is a good thing.