.timeout3 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #!/bin/bash
  2. #
  3. # The Bash shell script executes a command with a time-out.
  4. # Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
  5. # is blocked, then the subsequent SIGKILL (9) terminates it.
  6. #
  7. # Based on the Bash documentation example.
  8. # Hello Chet,
  9. # please find attached a "little easier" :-) to comprehend
  10. # time-out example. If you find it suitable, feel free to include
  11. # anywhere: the very same logic as in the original examples/scripts, a
  12. # little more transparent implementation to my taste.
  13. #
  14. # Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>
  15. scriptName="${0##*/}"
  16. declare -i DEFAULT_TIMEOUT=9
  17. declare -i DEFAULT_INTERVAL=1
  18. declare -i DEFAULT_DELAY=1
  19. # Timeout.
  20. declare -i timeout=DEFAULT_TIMEOUT
  21. # Interval between checks if the process is still alive.
  22. declare -i interval=DEFAULT_INTERVAL
  23. # Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
  24. declare -i delay=DEFAULT_DELAY
  25. function printUsage() {
  26. cat <<EOF
  27. Synopsis
  28. $scriptName [-t timeout] [-i interval] [-d delay] command
  29. Execute a command with a time-out.
  30. Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
  31. signal is blocked, then the subsequent SIGKILL (9) terminates it.
  32. -t timeout
  33. Number of seconds to wait for command completion.
  34. Default value: $DEFAULT_TIMEOUT seconds.
  35. -i interval
  36. Interval between checks if the process is still alive.
  37. Positive integer, default value: $DEFAULT_INTERVAL seconds.
  38. -d delay
  39. Delay between posting the SIGTERM signal and destroying the
  40. process by SIGKILL. Default value: $DEFAULT_DELAY seconds.
  41. As of today, Bash does not support floating point arithmetic (sleep does),
  42. therefore all delay/time values must be integers.
  43. EOF
  44. }
  45. # Options.
  46. while getopts ":t:i:d:" option; do
  47. case "$option" in
  48. t) timeout=$OPTARG ;;
  49. i) interval=$OPTARG ;;
  50. d) delay=$OPTARG ;;
  51. *) printUsage; exit 1 ;;
  52. esac
  53. done
  54. shift $((OPTIND - 1))
  55. # $# should be at least 1 (the command to execute), however it may be strictly
  56. # greater than 1 if the command itself has options.
  57. if (($# == 0 || interval <= 0)); then
  58. printUsage
  59. exit 1
  60. fi
  61. # kill -0 pid Exit code indicates if a signal may be sent to $pid process.
  62. (
  63. ((t = timeout))
  64. while ((t > 0)); do
  65. sleep $interval
  66. kill -0 $$ || exit 0
  67. ((t -= interval))
  68. done
  69. # Be nice, post SIGTERM first.
  70. # The 'exit 0' below will be executed if any preceeding command fails.
  71. kill -s SIGTERM $$ && kill -0 $$ || exit 0
  72. sleep $delay
  73. kill -s SIGKILL $$
  74. ) 2> /dev/null &
  75. exec "$@"