functions.xml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <sect1 id="ch07-functions">
  2. <title>Creating the functions script</title>
  3. <?dbhtml filename="functions.html" dir="chapter07"?>
  4. <para>Create the <filename>/etc/init.d/functions</filename> script by running
  5. the following command:</para>
  6. <para><screen><userinput>cat &gt; /etc/init.d/functions &lt;&lt; "EOF"</userinput>
  7. #!/bin/sh
  8. # Begin /etc/init.d/functions
  9. #
  10. # Set a few variables that influence the text that's printed on the
  11. # screen. The SET_COL variable starts the text in the column number
  12. # decided by the COL and WCOL section (as defined by the COL
  13. # variable). NORMAL prints text in normal mode.
  14. # SUCCESS prints text in a green colour and FAILURE prints text in a red
  15. # colour
  16. #
  17. # If COLUMNS hasn't been set yet (bash sets it but not when called as
  18. # sh), do it ourself
  19. if [ -z "$COLUMNS" ]
  20. then
  21. # Get the console device if we don't have it already
  22. # This is ok by the FHS as there is a fallback if
  23. # /usr/bin/tty isn't available, for example at bootup.
  24. test -x /usr/bin/tty &amp;&amp; CONSOLE=`/usr/bin/tty`
  25. test -z "$CONSOLE" &amp;&amp; CONSOLE=/dev/console
  26. # Get the console size (rows columns)
  27. SIZE=$(stty size &lt; $CONSOLE)
  28. # Strip off the rows leaving the columns
  29. COLUMNS=${SIZE#*\ }
  30. fi
  31. COL=$[$COLUMNS - 10]
  32. WCOL=$[$COLUMNS - 30]
  33. SET_COL="echo -en \\033[${COL}G"
  34. SET_WCOL="echo -en \\033[${WCOL}G"
  35. NORMAL="echo -en \\033[0;39m"
  36. SUCCESS="echo -en \\033[1;32m"
  37. WARNING="echo -en \\033[1;33m"
  38. FAILURE="echo -en \\033[1;31m"
  39. #
  40. # The evaluate_retval function evaluates the return value of the process
  41. # that was run just before this function was called. If the return value
  42. # was 0, indicating success, the print_status function is called with
  43. # the 'success' parameter. Otherwise the print_status function is called
  44. # with the failure parameter.
  45. #
  46. evaluate_retval()
  47. {
  48. if [ $? = 0 ]
  49. then
  50. print_status success
  51. else
  52. print_status failure
  53. fi
  54. }
  55. #
  56. # The print_status prints [ OK ] or [FAILED] to the screen. OK appears
  57. # in the colour defined by the SUCCESS variable and FAILED appears in
  58. # the colour defined by the FAILURE variable. Both are printed starting
  59. # in the column defined by the COL variable.
  60. #
  61. print_status()
  62. {
  63. #
  64. # If no parameters are given to the print_status function, print usage
  65. # information.
  66. #
  67. if [ $# = 0 ]
  68. then
  69. echo "Usage: print_status {success|failure}"
  70. return 1
  71. fi
  72. case "$1" in
  73. success)
  74. $SET_COL
  75. echo -n "[ "
  76. $SUCCESS
  77. echo -n "OK"
  78. $NORMAL
  79. echo " ]"
  80. ;;
  81. warning)
  82. $SET_COL
  83. echo -n "[ "
  84. $WARNING
  85. echo -n "ATTN"
  86. $NORMAL
  87. echo " ]"
  88. ;;
  89. failure)
  90. $SET_COL
  91. echo -n "["
  92. $FAILURE
  93. echo -n "FAILED"
  94. $NORMAL
  95. echo "]"
  96. ;;
  97. esac
  98. }
  99. #
  100. # The loadproc function starts a process (often a daemon) with
  101. # proper error checking
  102. #
  103. loadproc()
  104. {
  105. #
  106. # If no parameters are given to the print_status function, print usage
  107. # information.
  108. #
  109. if [ $# = 0 ]
  110. then
  111. echo "Usage: loadproc {program}"
  112. exit 1
  113. fi
  114. #
  115. # Find the basename of the first parameter (the daemon's name without
  116. # the path
  117. # that was provided so /usr/sbin/syslogd becomes plain 'syslogd' after
  118. # basename ran)
  119. #
  120. base=$(/usr/bin/basename $1)
  121. #
  122. # the pidlist variable will contains the output of the pidof command.
  123. # pidof will try to find the PID's that belong to a certain string;
  124. # $base in this case
  125. #
  126. pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base)
  127. pid=""
  128. for apid in $pidlist
  129. do
  130. if [ -d /proc/$apid ]
  131. then
  132. pid="$pid $apid"
  133. fi
  134. done
  135. #
  136. # If the $pid variable contains anything (from the previous for loop) it
  137. # means the daemon is already running
  138. #
  139. if [ ! -n "$pid" ]
  140. then
  141. #
  142. # Empty $pid variable means it's not running, so we run "$@" (all
  143. # parameters giving to this function from the script) and then check the
  144. # return value
  145. #
  146. "$@"
  147. evaluate_retval
  148. else
  149. #
  150. # The variable $pid was not empty, meaning it was already running. We'll
  151. # print [ ATTN ] now
  152. #
  153. $SET_WCOL
  154. echo -n "Already running"
  155. print_status warning
  156. fi
  157. }
  158. #
  159. # The killproc function kills a process with proper error checking
  160. #
  161. killproc()
  162. {
  163. #
  164. # If no parameters are given to the print_status function, print usage
  165. # information.
  166. #
  167. if [ $# = 0 ]
  168. then
  169. echo "Usage: killproc {program} [signal]"
  170. exit 1
  171. fi
  172. #
  173. # Find the basename of the first parameter (the daemon's name without
  174. # the path
  175. # that was provided so /usr/sbin/syslogd becomes plain 'syslogd' after
  176. # basename ran)
  177. #
  178. base=$(/usr/bin/basename $1)
  179. #
  180. # Check if we gave a signal to kill the process with (like -HUP, -TERM,
  181. # -KILL, etc) to this function (the second parameter). If no second
  182. # parameter was provided set the nolevel variable. Else set the
  183. # killlevel variable to the value of $2 (the second parameter)
  184. #
  185. if [ "$2" != "" ]
  186. then
  187. killlevel=-$2
  188. else
  189. nolevel=1
  190. fi
  191. #
  192. # the pidlist variable will contains the output of the pidof command.
  193. # pidof will try to find the PID's that belong to a certain string;
  194. # $base in this case
  195. #
  196. pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base)
  197. pid=""
  198. for apid in $pidlist
  199. do
  200. if [ -d /proc/$apid ]
  201. then
  202. pid="$pid $apid"
  203. fi
  204. done
  205. #
  206. # If $pid contains something from the previous for loop it means one or
  207. # more PID's were found that belongs to the processes to be killed
  208. #
  209. if [ -n "$pid" ]
  210. then
  211. #
  212. # If no kill level was specified we'll try -TERM first and then sleep
  213. # for 2 seconds to allow the kill to be completed
  214. #
  215. if [ "$nolevel" = 1 ]
  216. then
  217. /bin/kill -TERM $pid
  218. #
  219. # If after -TERM the PID still exists we'll wait 2 seconds before
  220. # trying to kill it with -KILL. If the PID still exist after that, wait
  221. # two more seconds. If the PIDs still exist by then it's safe to assume
  222. # that we cannot kill these PIDs.
  223. #
  224. if /bin/ps h $pid &gt;/dev/null 2&gt;&amp;1
  225. then
  226. /usr/bin/sleep 2
  227. if /bin/ps h $pid &gt; /dev/null 2&gt;&amp;1
  228. then
  229. /bin/kill -KILL $pid
  230. if /bin/ps h $pid &gt; /dev/null 2&gt;&amp;1
  231. then
  232. /usr/bin/sleep 2
  233. fi
  234. fi
  235. fi
  236. /bin/ps h $pid &gt;/dev/null 2&gt;&amp;1
  237. if [ $? = 0 ]
  238. then
  239. #
  240. # If after the -KILL it still exists it can't be killed for some reason
  241. # and we'll print [FAILED]
  242. #
  243. print_status failure
  244. else
  245. #
  246. # It was killed, remove possible stale PID file in /var/run and
  247. # print [ OK ]
  248. #
  249. /bin/rm -f /var/run/$base.pid
  250. print_status success
  251. fi
  252. else
  253. #
  254. # A kill level was provided. Kill with the provided kill level and wait
  255. # for 2 seconds to allow the kill to be completed
  256. #
  257. /bin/kill $killlevel $pid
  258. if /bin/ps h $pid &gt; /dev/null 2&gt;&amp;1
  259. then
  260. /usr/bin/sleep 2
  261. fi
  262. /bin/ps h $pid &gt;/dev/null 2&gt;&amp;1
  263. if [ $? = 0 ]
  264. then
  265. #
  266. # If ps' return value is 0 it means it ran ok which indicates that the
  267. # PID still exists. This means the process wasn't killed properly with
  268. # the signal provided. Print [FAILED]
  269. #
  270. print_status failure
  271. else
  272. #
  273. # If the return value was 1 or higher it means the PID didn't exist
  274. # anymore which means it was killed successfully. Remove possible stale
  275. # PID file and print [ OK ]
  276. #
  277. /bin/rm -f /var/run/$base.pid
  278. print_status success
  279. fi
  280. fi
  281. else
  282. #
  283. # The PID didn't exist so we can't attempt to kill it. Print [ ATTN ]
  284. #
  285. $SET_WCOL
  286. echo -n "Not running"
  287. print_status warning
  288. fi
  289. }
  290. #
  291. # The reloadproc functions sends a signal to a daemon telling it to
  292. # reload it's configuration file. This is almost identical to the
  293. # killproc function with the exception that it won't try to kill it with
  294. # a -KILL signal (aka -9)
  295. #
  296. reloadproc()
  297. {
  298. #
  299. # If no parameters are given to the print_status function, print usage
  300. # information.
  301. #
  302. if [ $# = 0 ]
  303. then
  304. echo "Usage: reloadproc {program} [signal]"
  305. exit 1
  306. fi
  307. #
  308. # Find the basename of the first parameter (the daemon's name without
  309. # the path that was provided so /usr/sbin/syslogd becomes plain 'syslogd'
  310. # after basename ran)
  311. #
  312. base=$(/usr/bin/basename $1)
  313. #
  314. # Check if we gave a signal to send to the process (like -HUP)
  315. # to this function (the second parameter). If no second
  316. # parameter was provided set the nolevel variable. Else set the
  317. # killlevel variable to the value of $2 (the second parameter)
  318. #
  319. if [ -n "$2" ]
  320. then
  321. killlevel=-$2
  322. else
  323. nolevel=1
  324. fi
  325. #
  326. # the pidlist variable will contains the output of the pidof command.
  327. # pidof will try to find the PID's that belong to a certain string;
  328. # $base in this case
  329. #
  330. pidlist=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $base)
  331. pid=""
  332. for apid in $pidlist
  333. do
  334. if [ -d /proc/$apid ]
  335. then
  336. pid="$pid $apid"
  337. fi
  338. done
  339. #
  340. # If $pid contains something from the previous for loop it means one or
  341. # more PID's were found that belongs to the processes to be reloaded
  342. #
  343. if [ -n "$pid" ]
  344. then
  345. #
  346. # If nolevel was set we will use the default reload signal SIGHUP.
  347. #
  348. if [ "$nolevel" = 1 ]
  349. then
  350. /bin/kill -SIGHUP $pid
  351. evaluate_retval
  352. else
  353. #
  354. # Else we will use the provided signal
  355. #
  356. /bin/kill $killlevel $pid
  357. evaluate_retval
  358. fi
  359. else
  360. #
  361. # If $pid is empty no PID's have been found that belong to the process.
  362. # Print [ ATTN ]
  363. #
  364. $SET_WCOL
  365. echo -n "Not running"
  366. print_status warning
  367. fi
  368. }
  369. #
  370. # The statusproc function will try to find out if a process is running
  371. # or not
  372. #
  373. statusproc()
  374. {
  375. #
  376. # If no parameters are given to the print_status function, print usage
  377. # information.
  378. #
  379. if [ $# = 0 ]
  380. then
  381. echo "Usage: status {program}"
  382. return 1
  383. fi
  384. #
  385. # $pid will contain a list of PID's that belong to a process
  386. #
  387. pid=$(/bin/pidof -o $$ -o $PPID -o %PPID -x $1)
  388. if [ -n "$pid" ]
  389. then
  390. #
  391. # If $pid contains something, the process is running, print the contents
  392. # of the $pid variable
  393. #
  394. echo "$1 running with Process ID $pid"
  395. return 0
  396. fi
  397. #
  398. # If $pid doesn't contain it check if a PID file exists and inform the
  399. # user about this stale file.
  400. #
  401. if [ -f /var/run/$1.pid ]
  402. then
  403. pid=$(/usr/bin/head -1 /var/run/$1.pid)
  404. if [ -n "$pid" ]
  405. then
  406. echo "$1 not running but /var/run/$1.pid exists"
  407. return 1
  408. fi
  409. else
  410. echo "$1 is not running"
  411. fi
  412. }
  413. # End /etc/init.d/functions
  414. <userinput>EOF</userinput></screen></para>
  415. </sect1>