You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

560 lines
16 KiB

  1. #!/bin/sh
  2. #
  3. # invoke-rc.d.sysvinit - Executes initscript actions
  4. #
  5. # SysVinit /etc/rc?.d version for Debian's sysvinit package
  6. #
  7. # Copyright (C) 2000,2001 Henrique de Moraes Holschuh <hmh@debian.org>
  8. #
  9. # This program is free software; you can redistribute it and/or modify it
  10. # under the terms of the GNU General Public License as published by the Free
  11. # Software Foundation; either version 2 of the License, or (at your option)
  12. # any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful, but
  15. # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  17. # for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License along
  20. # with this program; if not, write to the Free Software Foundation, Inc.,
  21. # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  22. # Constants
  23. RUNLEVELHELPER=/sbin/runlevel
  24. POLICYHELPER=/usr/sbin/policy-rc.d
  25. INITDPREFIX=/etc/init.d/
  26. RCDPREFIX=/etc/rc
  27. # Options
  28. BEQUIET=
  29. MODE=
  30. ACTION=
  31. FALLBACK=
  32. NOFALLBACK=
  33. FORCE=
  34. RETRY=
  35. RETURNFAILURE=
  36. RC=
  37. is_systemd=
  38. is_openrc=
  39. # Shell options
  40. set +e
  41. dohelp () {
  42. #
  43. # outputs help and usage
  44. #
  45. cat <<EOF
  46. invoke-rc.d, Debian/SysVinit (/etc/rc?.d) initscript subsystem.
  47. Copyright (c) 2000,2001 Henrique de Moraes Holschuh <hmh@debian.org>
  48. Usage:
  49. invoke-rc.d [options] <basename> <action> [extra parameters]
  50. basename - Initscript ID, as per update-rc.d(8)
  51. action - Initscript action. Known actions are:
  52. start, [force-]stop, [try-]restart,
  53. [force-]reload, status
  54. WARNING: not all initscripts implement all of the above actions.
  55. extra parameters are passed as is to the initscript, following
  56. the action (first initscript parameter).
  57. Options:
  58. --quiet
  59. Quiet mode, no error messages are generated.
  60. --force
  61. Try to run the initscript regardless of policy and subsystem
  62. non-fatal errors.
  63. --try-anyway
  64. Try to run init script even if a non-fatal error is found.
  65. --disclose-deny
  66. Return status code 101 instead of status code 0 if
  67. initscript action is denied by local policy rules or
  68. runlevel constrains.
  69. --query
  70. Returns one of status codes 100-106, does not run
  71. the initscript. Implies --disclose-deny and --no-fallback.
  72. --no-fallback
  73. Ignores any fallback action requests by the policy layer.
  74. Warning: this is usually a very *bad* idea for any actions
  75. other than "start".
  76. --help
  77. Outputs help message to stdout
  78. EOF
  79. }
  80. printerror () {
  81. #
  82. # prints an error message
  83. # $* - error message
  84. #
  85. if test x${BEQUIET} = x ; then
  86. echo `basename $0`: "$*" >&2
  87. fi
  88. }
  89. formataction () {
  90. #
  91. # formats a list in $* into $printaction
  92. # for human-friendly printing to stderr
  93. # and sets $naction to action or actions
  94. #
  95. printaction=`echo $* | sed 's/ /, /g'`
  96. if test $# -eq 1 ; then
  97. naction=action
  98. else
  99. naction=actions
  100. fi
  101. }
  102. querypolicy () {
  103. #
  104. # queries policy database
  105. # returns: $RC = 104 - ok, run
  106. # $RC = 101 - ok, do not run
  107. # other - exit with status $RC, maybe run if $RETRY
  108. # initial status of $RC is taken into account.
  109. #
  110. policyaction="${ACTION}"
  111. if test x${RC} = "x101" ; then
  112. if test "${ACTION}" = "start" || test "${ACTION}" = "restart" || test "${ACTION}" = "try-restart"; then
  113. policyaction="(${ACTION})"
  114. fi
  115. fi
  116. if test "x${POLICYHELPER}" != x && test -x "${POLICYHELPER}" ; then
  117. FALLBACK=`${POLICYHELPER} ${BEQUIET} ${INITSCRIPTID} "${policyaction}" ${RL}`
  118. RC=$?
  119. formataction ${ACTION}
  120. case ${RC} in
  121. 0) RC=104
  122. ;;
  123. 1) RC=105
  124. ;;
  125. 101) if test x${FORCE} != x ; then
  126. printerror Overriding policy-rc.d denied execution of ${printaction}.
  127. RC=104
  128. else
  129. printerror policy-rc.d denied execution of ${printaction}.
  130. fi
  131. ;;
  132. esac
  133. if test x${MODE} != xquery ; then
  134. case ${RC} in
  135. 105) printerror policy-rc.d query returned \"behaviour undefined\",
  136. printerror assuming \"${printaction}\" is allowed.
  137. RC=104
  138. ;;
  139. 106) formataction ${FALLBACK}
  140. if test x${FORCE} = x ; then
  141. if test x${NOFALLBACK} = x ; then
  142. ACTION="${FALLBACK}"
  143. printerror executing ${naction} \"${printaction}\" instead due to policy-rc.d request.
  144. RC=104
  145. else
  146. printerror ignoring policy-rc.d fallback request: ${printaction}.
  147. RC=101
  148. fi
  149. else
  150. printerror ignoring policy-rc.d fallback request: ${printaction}.
  151. RC=104
  152. fi
  153. ;;
  154. esac
  155. fi
  156. case ${RC} in
  157. 100|101|102|103|104|105|106) ;;
  158. *) printerror WARNING: policy-rc.d returned unexpected error status ${RC}, 102 used instead.
  159. RC=102
  160. ;;
  161. esac
  162. else
  163. if test ! -e "/sbin/init" ; then
  164. if test x${FORCE} != x ; then
  165. printerror "WARNING: No init system and policy-rc.d missing, but force specified so proceeding."
  166. else
  167. printerror "WARNING: No init system and policy-rc.d missing! Defaulting to block."
  168. RC=101
  169. fi
  170. fi
  171. if test x${RC} = x ; then
  172. RC=104
  173. fi
  174. fi
  175. return
  176. }
  177. verifyparameter () {
  178. #
  179. # Verifies if $1 is not null, and $# = 1
  180. #
  181. if test $# -eq 0 ; then
  182. printerror syntax error: invalid empty parameter
  183. exit 103
  184. elif test $# -ne 1 ; then
  185. printerror syntax error: embedded blanks are not allowed in \"$*\"
  186. exit 103
  187. fi
  188. return
  189. }
  190. ##
  191. ## main
  192. ##
  193. ## Verifies command line arguments
  194. if test $# -eq 0 ; then
  195. printerror syntax error: missing required parameter, --help assumed
  196. dohelp
  197. exit 103
  198. fi
  199. state=I
  200. while test $# -gt 0 && test ${state} != III ; do
  201. case "$1" in
  202. --help) dohelp
  203. exit 0
  204. ;;
  205. --quiet) BEQUIET=--quiet
  206. ;;
  207. --force) FORCE=yes
  208. RETRY=yes
  209. ;;
  210. --try-anyway)
  211. RETRY=yes
  212. ;;
  213. --disclose-deny)
  214. RETURNFAILURE=yes
  215. ;;
  216. --query) MODE=query
  217. RETURNFAILURE=yes
  218. ;;
  219. --no-fallback)
  220. NOFALLBACK=yes
  221. ;;
  222. --*) printerror syntax error: unknown option \"$1\"
  223. exit 103
  224. ;;
  225. *) case ${state} in
  226. I) verifyparameter $1
  227. INITSCRIPTID=$1
  228. ;;
  229. II) verifyparameter $1
  230. ACTION=$1
  231. ;;
  232. esac
  233. state=${state}I
  234. ;;
  235. esac
  236. shift
  237. done
  238. if test ${state} != III ; then
  239. printerror syntax error: missing required parameter
  240. exit 103
  241. fi
  242. #NOTE: It may not be obvious, but "$@" from this point on must expand
  243. #to the extra initscript parameters, except inside functions.
  244. if test -d /run/systemd/system ; then
  245. is_systemd=1
  246. UNIT="${INITSCRIPTID%.sh}.service"
  247. elif test -f /run/openrc/softlevel ; then
  248. is_openrc=1
  249. elif test ! -f "${INITDPREFIX}${INITSCRIPTID}" ; then
  250. ## Verifies if the given initscript ID is known
  251. ## For sysvinit, this error is critical
  252. printerror unknown initscript, ${INITDPREFIX}${INITSCRIPTID} not found.
  253. fi
  254. ## Queries sysvinit for the current runlevel
  255. if [ ! -x ${RUNLEVELHELPER} ] || ! RL=`${RUNLEVELHELPER}`; then
  256. if [ -n "$is_systemd" ] && systemctl is-active --quiet sysinit.target; then
  257. # under systemd, the [2345] runlevels are only set upon reaching them;
  258. # if we are past sysinit.target (roughly equivalent to rcS), consider
  259. # this as runlevel 5 (this is only being used for validating rcN.d
  260. # symlinks, so the precise value does not matter much)
  261. RL=5
  262. else
  263. printerror "could not determine current runlevel"
  264. # this usually fails in schroots etc., ignore failure (#823611)
  265. RL=
  266. fi
  267. fi
  268. # strip off previous runlevel
  269. RL=${RL#* }
  270. ## Running ${RUNLEVELHELPER} to get current runlevel do not work in
  271. ## the boot runlevel (scripts in /etc/rcS.d/), as /var/run/utmp
  272. ## contains runlevel 0 or 6 (written at shutdown) at that point.
  273. if test x${RL} = x0 || test x${RL} = x6 ; then
  274. if ps -fp 1 | grep -q 'init boot' ; then
  275. RL=S
  276. fi
  277. fi
  278. ## Handles shutdown sequences VERY safely
  279. ## i.e.: forget about policy, and do all we can to run the script.
  280. ## BTW, why the heck are we being run in a shutdown runlevel?!
  281. if test x${RL} = x0 || test x${RL} = x6 ; then
  282. FORCE=yes
  283. RETRY=yes
  284. POLICYHELPER=
  285. BEQUIET=
  286. printerror "-----------------------------------------------------"
  287. printerror "WARNING: 'invoke-rc.d ${INITSCRIPTID} ${ACTION}' called"
  288. printerror "during shutdown sequence."
  289. printerror "enabling safe mode: initscript policy layer disabled"
  290. printerror "-----------------------------------------------------"
  291. fi
  292. ## Verifies the existance of proper S??initscriptID and K??initscriptID
  293. ## *links* in the proper /etc/rc?.d/ directory
  294. verifyrclink () {
  295. #
  296. # verifies if parameters are non-dangling symlinks
  297. # all parameters are verified
  298. #
  299. doexit=
  300. while test $# -gt 0 ; do
  301. if test ! -L "$1" ; then
  302. printerror not a symlink: $1
  303. doexit=102
  304. fi
  305. if test ! -f "$1" ; then
  306. printerror dangling symlink: $1
  307. doexit=102
  308. fi
  309. shift
  310. done
  311. if test x${doexit} != x && test x${RETRY} = x; then
  312. exit ${doexit}
  313. fi
  314. return 0
  315. }
  316. testexec () {
  317. #
  318. # returns true if any of the parameters is
  319. # executable (after following links)
  320. #
  321. while test $# -gt 0 ; do
  322. if test -x "$1" ; then
  323. return 0
  324. fi
  325. shift
  326. done
  327. return 1
  328. }
  329. RC=
  330. ###
  331. ### LOCAL POLICY: Enforce that the script/unit is enabled. For SysV init
  332. ### scripts, this needs a start entry in either runlevel S or current runlevel
  333. ### to allow start or restart.
  334. if [ -n "$is_systemd" ]; then
  335. case ${ACTION} in
  336. start|restart|try-restart)
  337. # Note that systemd 215 does not yet support is-enabled for SysV scripts,
  338. # this works only with systemd >= 220-1 (systemd-sysv-install). Add a
  339. # simple fallback check which can be dropped after releasing stretch.
  340. if systemctl --quiet is-enabled "${UNIT}" 2>/dev/null || \
  341. ls ${RCDPREFIX}[S2345].d/S[0-9][0-9]${INITSCRIPTID} >/dev/null 2>&1; then
  342. RC=104
  343. elif systemctl --quiet is-active "${UNIT}" 2>/dev/null; then
  344. RC=104
  345. else
  346. RC=101
  347. fi
  348. ;;
  349. esac
  350. else
  351. # we do handle multiple links per runlevel
  352. # but we don't handle embedded blanks in link names :-(
  353. if test x${RL} != x ; then
  354. SLINK=`ls -d -Q ${RCDPREFIX}${RL}.d/S[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
  355. KLINK=`ls -d -Q ${RCDPREFIX}${RL}.d/K[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
  356. SSLINK=`ls -d -Q ${RCDPREFIX}S.d/S[0-9][0-9]${INITSCRIPTID} 2>/dev/null | xargs`
  357. verifyrclink ${SLINK} ${KLINK} ${SSLINK}
  358. fi
  359. case ${ACTION} in
  360. start|restart|try-restart)
  361. if testexec ${SLINK} ; then
  362. RC=104
  363. elif testexec ${KLINK} ; then
  364. RC=101
  365. elif testexec ${SSLINK} ; then
  366. RC=104
  367. else
  368. RC=101
  369. fi
  370. ;;
  371. esac
  372. fi
  373. # test if /etc/init.d/initscript is actually executable
  374. _executable=
  375. if [ -n "$is_systemd" ]; then
  376. _executable=1
  377. elif testexec "${INITDPREFIX}${INITSCRIPTID}"; then
  378. _executable=1
  379. fi
  380. if [ "$_executable" = "1" ]; then
  381. if test x${RC} = x && test x${MODE} = xquery ; then
  382. RC=105
  383. fi
  384. # call policy layer
  385. querypolicy
  386. case ${RC} in
  387. 101|104)
  388. ;;
  389. *) if test x${MODE} != xquery ; then
  390. printerror policy-rc.d returned error status ${RC}
  391. if test x${RETRY} = x ; then
  392. exit ${RC}
  393. else
  394. RC=102
  395. fi
  396. fi
  397. ;;
  398. esac
  399. else
  400. ###
  401. ### LOCAL INITSCRIPT POLICY: non-executable initscript; deny exec.
  402. ### (this is common sense, actually :^P )
  403. ###
  404. RC=101
  405. fi
  406. ## Handles --query
  407. if test x${MODE} = xquery ; then
  408. exit ${RC}
  409. fi
  410. setechoactions () {
  411. if test $# -gt 1 ; then
  412. echoaction=true
  413. else
  414. echoaction=
  415. fi
  416. }
  417. getnextaction () {
  418. saction=$1
  419. shift
  420. ACTION="$@"
  421. }
  422. ## Executes initscript
  423. ## note that $ACTION is a space-separated list of actions
  424. ## to be attempted in order until one suceeds.
  425. if test x${FORCE} != x || test ${RC} -eq 104 ; then
  426. if [ -n "$is_systemd" ] || testexec "${INITDPREFIX}${INITSCRIPTID}" ; then
  427. RC=102
  428. setechoactions ${ACTION}
  429. while test ! -z "${ACTION}" ; do
  430. getnextaction ${ACTION}
  431. if test ! -z ${echoaction} ; then
  432. printerror executing initscript action \"${saction}\"...
  433. fi
  434. if [ -n "$is_systemd" ]; then
  435. if [ -n "$DPKG_MAINTSCRIPT_PACKAGE" ]; then
  436. # If we are called by a maintainer script, chances are good that a
  437. # new or updated sysv init script was installed. Reload daemon to
  438. # pick up any changes.
  439. systemctl daemon-reload
  440. fi
  441. _state=$(systemctl -p LoadState show "${UNIT}" 2>/dev/null)
  442. # avoid deadlocks during bootup and shutdown from units/hooks
  443. # which call "invoke-rc.d service reload" and similar, since
  444. # the synchronous wait plus systemd's normal behaviour of
  445. # transactionally processing all dependencies first easily
  446. # causes dependency loops
  447. if ! systemctl --quiet is-active multi-user.target; then
  448. sctl_args="--job-mode=ignore-dependencies"
  449. fi
  450. case $saction in
  451. start|restart|try-restart)
  452. [ "$_state" != "LoadState=masked" ] || exit 0
  453. systemctl $sctl_args "${saction}" "${UNIT}" && exit 0
  454. ;;
  455. stop|status)
  456. systemctl $sctl_args "${saction}" "${UNIT}" && exit 0
  457. ;;
  458. reload)
  459. [ "$_state" != "LoadState=masked" ] || exit 0
  460. _canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
  461. if [ "$_canreload" = "CanReload=no" ]; then
  462. "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
  463. else
  464. systemctl $sctl_args reload "${UNIT}" && exit 0
  465. fi
  466. ;;
  467. force-stop)
  468. systemctl --signal=KILL kill "${UNIT}" && exit 0
  469. ;;
  470. force-reload)
  471. [ "$_state" != "LoadState=masked" ] || exit 0
  472. _canreload="$(systemctl -p CanReload show ${UNIT} 2>/dev/null)"
  473. if [ "$_canreload" = "CanReload=no" ]; then
  474. systemctl $sctl_args restart "${UNIT}" && exit 0
  475. else
  476. systemctl $sctl_args reload "${UNIT}" && exit 0
  477. fi
  478. ;;
  479. *)
  480. # We try to run non-standard actions by running
  481. # the init script directly.
  482. "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
  483. ;;
  484. esac
  485. elif [ -n "$is_openrc" ]; then
  486. rc-service "${INITSCRIPTID}" "${saction}" && exit 0
  487. else
  488. "${INITDPREFIX}${INITSCRIPTID}" "${saction}" "$@" && exit 0
  489. fi
  490. RC=$?
  491. if test ! -z "${ACTION}" ; then
  492. printerror action \"${saction}\" failed, trying next action...
  493. fi
  494. done
  495. printerror initscript ${INITSCRIPTID}, action \"${saction}\" failed.
  496. if [ -n "$is_systemd" ] && [ "$saction" = start -o "$saction" = restart -o "$saction" = "try-restart" ]; then
  497. systemctl status --full --no-pager "${UNIT}" || true
  498. fi
  499. exit ${RC}
  500. fi
  501. exit 102
  502. fi
  503. ## Handles --disclose-deny and denied "status" action (bug #381497)
  504. if test ${RC} -eq 101 && test x${RETURNFAILURE} = x ; then
  505. if test "x${ACTION%% *}" = "xstatus"; then
  506. printerror emulating initscript action \"status\", returning \"unknown\"
  507. RC=4
  508. else
  509. RC=0
  510. fi
  511. else
  512. formataction ${ACTION}
  513. printerror initscript ${naction} \"${printaction}\" not executed.
  514. fi
  515. exit ${RC}