Advertisement
Guest User

BackgroundProcess

a guest
Sep 18th, 2013
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.15 KB | None | 0 0
  1. #!/bin/bash
  2. #Written by Manuel Iglesias. glesialo@gmail.com
  3.  
  4. CommandName=${0##*/}
  5. CommandOptionString="-c"
  6. RunInBackgroundOptionString="-b"
  7. KillProcessOptionString="-k"
  8. ProcessFinishedOptionString="-f"
  9. TempDir="/tmp"
  10. KillProcessTimeout="1" # Max time for killed process's parent to save child process' info. '$CommandName -k ' fails if parent still running after timeout.
  11. KillSignal=HUP
  12.  
  13. ########### Functions. BEGIN.
  14. echoE()
  15. {
  16. echo -e $* 1>&2
  17. return 0
  18. }
  19.  
  20. Usage()
  21. {
  22. echoE "'$CommandName' can be used to launch/control a process running in background."
  23. echoE "Usage: '$CommandName $CommandOptionString Command [Param [Param...]]'."
  24. echoE "\tLaunches 'Command [Param [Param...]]' in background."
  25. echoE "\tOutputs background process Id. Exitcode 0 if successful."
  26. echoE "Usage: '$CommandName ProcessPid'."
  27. echoE "\tOutputs background process' info (See below)."
  28. echoE "\tExitcode 0 if process is valid and no longer running (Info valid)."
  29. echoE "\tExitcode 1 if process valid and still running (Info not valid)."
  30. echoE "\tExitcode non 0 if not a valid process or any other problems"
  31. echoE "\t (Info not valid)."
  32. echoE "Usage: '$CommandName $ProcessFinishedOptionString ProcessPid'."
  33. echoE "\tChecks if process with 'ProcessPid' Pid has finished running."
  34. echoE "\tExitcode 0 if process is valid and no longer running"
  35. echoE "\tExitcode 1 if process valid and still running."
  36. echoE "\tExitcode non 0 if not a valid process or any other problems."
  37. echoE "\tDoes not output any info."
  38. echoE "Usage: '$CommandName $KillProcessOptionString ProcessPid'."
  39. echoE "\tKills process with 'ProcessPid' Pid (Previously"
  40. echoE "\t launched by '$CommandName')."
  41. echoE "\tOutputs background process' info (See below)."
  42. echoE "\tExitcode 0 if valid process and killed successfully"
  43. echoE "\t (Or had exited already) and info read successfully."
  44. echoE "Background process' info:"
  45. echoE "\tText that when sourced (with 'eval') gives values to following"
  46. echoE "\tvariables:"
  47. echoE "\t 'CommandLine': Command and parameters of process when launched."
  48. echoE "\t 'ElapsedTime': Time (in seconds) the process was running."
  49. echoE "\t 'ExitCode': Exit code of process."
  50. echoE "\t 'StandardOut': Output generated by process while running."
  51. echoE "\t 'StandardError': Error output generated by process while running."
  52. echoE "\tNote: To avoid mismatch in the number of \",',\`,ยด (which would cause"
  53. echoE "\t 'eval' to fail) each of them can be replaced by \\\" in 'StandardOut'"
  54. echoE "\t & 'StandardError' (Some commands output: \`Error message') by using"
  55. echoE "\t function 'CleanText' (See \$COMMON_BIN_DIR/BashCodeRepository)."
  56. echoE "Note: Normal usage sequence:"
  57. echoE "\tLaunch a process in background and get its Pid."
  58. echoE "\tDo other tasks."
  59. echoE "\tCheck if backgroung process has finished running"
  60. echoE "\t using '$CommandName' and Pid."
  61. echoE "\tRead info when backgroung process has finished."
  62. echoE "\tSource background process' info and use Variables' contents."
  63. echoE "\tIf background process has not finished in the allotted time"
  64. echoE "\t kill it with '$CommandName' (And get info of killed process)."
  65. echoE "Please read \$COMMON_BIN_DIR/BashCodeRepository for examples of usage."
  66. echoE
  67. return 0
  68. }
  69. ########### Functions. END.
  70.  
  71. CommandOption=false;RunInBackgroundOption=false;KillProcessOption=false;ProcessFinishedOption=false
  72. if [ "$1" == "$CommandOptionString" ]
  73. then
  74. CommandOption=true
  75. shift
  76. else
  77. if [ "$1" == "$RunInBackgroundOptionString" ]
  78. then
  79. RunInBackgroundOption=true
  80. shift
  81. else
  82. if [ "$1" == "$KillProcessOptionString" ]
  83. then
  84. KillProcessOption=true
  85. shift
  86. else
  87. if [ "$1" == "$ProcessFinishedOptionString" ]
  88. then
  89. ProcessFinishedOption=true
  90. shift
  91. fi
  92. fi
  93. fi
  94. fi
  95.  
  96. if [ $# -lt 1 ] || [ "$1" == "-h" ] || [ "$1" == "-?" ] || [ "$1" == "--help" ] || [ "$1" == "-help" ]
  97. then
  98. Usage
  99. exit 64
  100. fi
  101.  
  102. if $CommandOption
  103. then
  104. if ! type "$1" &>/dev/null
  105. then
  106. echoE "$CommandName: Command '$1' not in \$PATH. Aborting!"
  107. exit 127
  108. fi
  109. # 'coproc': Equivalent to ending command with '&'. '&' does not work if shell invoked with `` (ProcessId=`BackgroundProcess -c Command`)
  110. # &>/dev/null so that no error message is given when killed. Also to allow background processes to be launched from this background process (pipes?)
  111. if coproc $CommandName $RunInBackgroundOptionString "$@" &>/dev/null
  112. then
  113. eval "exec ${COPROC[0]}>&-" #Close coproc stdout pipe (See Books/Science/Computer_Science/Linux/Bash_scripting/Bash_Co_Processes)
  114. eval "exec ${COPROC[1]}<&-" #Close coproc stdin pipe (See Books/Science/Computer_Science/Linux/Bash_scripting/Bash_Co_Processes)
  115. echo "$!"
  116. exit 0
  117. else
  118. echoE "$CommandName: Launching in background with 'coproc' failed with ExitCode: $?. Aborting!" # Should never happen but... just in case ;-)
  119. exit 70
  120. fi
  121. fi
  122.  
  123. if $RunInBackgroundOption
  124. then
  125. TempFile="${TempDir}/${CommandName}_$$"
  126. TempErrorFile="${TempFile}.Error"
  127. >$TempErrorFile # So that other users can not read file
  128. chmod 600 $TempErrorFile # So that other users can not read file
  129. TempOutFile="${TempFile}.Out"
  130. >$TempOutFile # So that other users can not read file
  131. chmod 600 $TempOutFile # So that other users can not read file
  132. cd $TempDir # So that child process uses it as working directory (And does not tie up current wd).
  133. exec 0<&- # Close stdin
  134. exec 1>&- # Close stdout
  135. exec 2>&- # Close stderr
  136. StartTime=`date +%s` # Seconds since 1970โˆ’01โˆ’01
  137. 1>$TempOutFile 2>$TempErrorFile "$@"
  138. ExitCode=$?
  139. let ElapsedTime=`date +%s`-$StartTime
  140. echo -e "CommandLine=\"$@\"\n#\nElapsedTime=${ElapsedTime}\n#\nExitCode=${ExitCode}\n#\nStandardOut=\"`cat $TempOutFile`\"\n#\nStandardError=\"`cat $TempErrorFile`\"\n#" >$TempFile
  141. rm -f $TempErrorFile $TempOutFile
  142. exit 0
  143. fi
  144.  
  145. if [ $# -ne 1 ]
  146. then
  147. Usage
  148. exit 64
  149. fi
  150.  
  151. TempFile="${TempDir}/${CommandName}_$1"
  152.  
  153. if ProcessCommandName=`2>/dev/null ps --pid=$1 h -o comm`
  154. then
  155. # If $CommandName contains $ProcessCommandName (ps returns only the 15 first characters of command).
  156. if [ "$CommandName" != "${CommandName/${ProcessCommandName}/}" ]
  157. then
  158. if $KillProcessOption
  159. then
  160. for Grandchild in `ps -o pid --no-headers --ppid $1`
  161. do
  162. pkill -${KillSignal} -P $Grandchild &>/dev/null # Kill BackgroundProcess' children's children (grandchildren)
  163. done
  164. pkill -${KillSignal} -P $1 &>/dev/null # -P means kill processes whose parent process ID is listed. Here: kill BackgroundProcess' children
  165. let "KillProcessTimeout = $KillProcessTimeout * 10" # Will be checked at 1/10 seconds
  166. while &>/dev/null ps --pid=$1 && [ $KillProcessTimeout -gt 0 ]
  167. do
  168. sleep 0.1
  169. done
  170. if ! &>/dev/null ps --pid=$1
  171. then
  172. if [ -f $TempFile ]
  173. then
  174. cat $TempFile
  175. rm -f $TempFile
  176. exit 0
  177. else
  178. echoE "$CommandName: Process killed but temporary file not found. No record of process '$1'."
  179. exit 70
  180. fi
  181. else
  182. echoE "$CommandName: Warning! Process '$1' could not be killed."
  183. exit 70
  184. fi
  185. fi
  186. echoE "$CommandName: Process '$1' still running."
  187. exit 1
  188. else
  189. echoE "$CommandName: Process '$1' running but not an instance of '$CommandName'. Aborting."
  190. exit 70
  191. fi
  192. fi
  193.  
  194. if [ -f $TempFile ]
  195. then
  196. if $ProcessFinishedOption
  197. then
  198. exit 0
  199. fi
  200. if $KillProcessOption
  201. then
  202. echoE "$CommandName: Process '$1' has already exited. Kill request ignored."
  203. fi
  204. cat $TempFile
  205. rm -f $TempFile
  206. else
  207. echoE "$CommandName: Process not running and temporary file not found. No record of process '$1'."
  208. exit 70
  209. fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement