Sysvinit

基於 bash 腳本的 init.d 失敗,為什麼?

  • April 3, 2020

我有這個init.d腳本(/etc/init.d/ctrlme):

#!/lib/init/init-d-script

### BEGIN INIT INFO
# Provides:          ctrlme
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ctrlme
# Description:       ctrlme
### END INIT INFO

# sudo cp -v /home/gigikent/bin/init.d-services/ctrlme /etc/init.d/; sudo chown root: /etc/init.d/ctrlme
#
# https://www.pks.mpg.de/~mueller/docs/suse10.1/suselinux-manual_en/manual/sec.boot.init.html   
#

NAME=ctrlme
PIDFILE=/run/ctrlme.pid
DAEMON=/bin/bash -c '/home/gigikent/x.sh ctrlme'
DESC=ctrlme

# . /lib/lsb/init-functions
# 
# case "$1" in
#   start)
#         /home/gigikent/x.sh ctrlme
#     ;;
#   stop|restart|force-reload) 
#         exit 0
#     ;;
#   *) echo "Usage: $0 {start|stop|restart|force-reload}" >&2; exit 1 ;;
# esac

啟動時失敗:

Jun 16 18:57:13 gigikent.go.ro ctrlme[28454]: /lib/init/init-d-script: 20: /etc/init.d/ctrlme: -c: not found
Jun 16 18:57:13 gigikent.go.ro systemd[1]: ctrlme.service: Succeeded.
-- Subject: Unit succeeded
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- 
-- The unit ctrlme.service has successfully entered the 'dead' state.

執行/bin/bash -c '/home/gigikent/x.sh ctrlme'命令按預期工作。

為什麼會發生這種情況,我應該如何解決這個問題?

系統資訊:

Ubuntu 19.04

DAEMON=/bin/bash -c '/home/adr/x.sh ctrlme'

這應該是:

守護程序="/bin/bash"
DAEMON_ARGS="'/home/adr/x.sh ctrlme'"

或者,更好的是:

DAEMON="/home/adr/x.sh"
DAEMON_ARGS="ctrlme"

進一步閱讀

分析/lib/init/init-d-script來源觀察到:

do_start_cmd() {
   start-stop-daemon --start --quiet ${PIDFILE:+--pidfile ${PIDFILE}} \
       $START_ARGS \
       --startas $DAEMON --name $NAME --exec $DAEMON --test

這對於腳本(例如 bash 腳本)不起作用,因為根據http://man7.org/linux/man-pages/man8/start-stop-daemon.8.html DAEMON應該是pathname

-a, --startas pathname
       With --start, start the process specified by pathname.  If not
       specified, defaults to the argument given to --exec.

也可以將上述用法start-stop-daemon與來自的用法進行比較/lib/lsb/init-functions,例如:

start_daemon () {
   ...
   exec="$1"; shift
   ...
   if [ "$force" ]; then
       /sbin/start-stop-daemon $args \
       --chdir "$PWD" --startas $exec --pidfile /dev/null -- "$@"
   ...

start_daemon與例如一起 使用時:

start_daemon -p /run/ctrlme.pid /bin/bash /home/adr/x.sh ctrlme

而不是while$exec將是+意味著當沒有一個時必須使用而不是使用它的變數。/bin/bash``"$@"``/home/adr/x.sh``ctrlme``pathname``start_daemon()``/lib/init/init-d-script``DAEMON

更新

我也讓這個答案,因為更好地突出問題和解決方案。另一方面,請注意這部分結論是錯誤的:

當沒有pathname一個時將不得不使用 start_daemon()而不是/lib/init/init-d-script

確實,可以使用DAEMONwith ,DAEMON_ARGS如已接受的答案所述。這是真的,因為在第二次呼叫受益的情況下do_start_cmd()呼叫start-stop-daemon了 2 次DAEMON_ARGS

do_start_cmd() {
   start-stop-daemon --start --quiet ${PIDFILE:+--pidfile ${PIDFILE}} \
       $START_ARGS \
       --startas $DAEMON --name $NAME --exec $DAEMON --test > /dev/null \
       || return 1
   start-stop-daemon --start --quiet ${PIDFILE:+--pidfile ${PIDFILE}} \
       $START_ARGS \
       --startas $DAEMON --name $NAME --exec $DAEMON -- $DAEMON_ARGS \
       || return 2

引用自:https://unix.stackexchange.com/questions/525266