최근에 가상 머신(Debian 7.8)에서 실행되는 로컬 서비스를 물리적 머신(Debian 8.5)으로 마이그레이션했는데 마이그레이션 후 초기화 스크립트가 작동을 멈췄습니다. Wheezy와 Jessie 사이에 초기화 프로세스 등에 몇 가지 주요 변경 사항이 있었다는 것을 알고 있지만, 제가 아는 한 변경 사항은 여전히 제 초기화 스크립트와 호환되어야 합니다. 위에서 설명한 대로 스크립트를 "LSB화"했다고 확신합니다.데비안 위키어쨌든, 여전히 오래된 스켈레톤 예제와 매우 유사합니다.
나는 무슨 일이 일어나고 있는지 알아내기 위해 많은 시도를 해왔고 스크립트가 (보통?) 충돌하거나 적어도 지연되는 것을 확신합니다 /lib/lsb/init-functions
. 왜 이런 일이 발생하는지 모르겠습니다.
이 결론에 도달한 후 init 스크립트를 init 함수를 사용하지 않는 (다소 서투른) 짧은 버전으로 다듬었습니다. 이는 bash 프로세스를 하위 하위 쉘로 분기하여 고아가 되도록 했습니다. 이것은 조금 더 잘 작동하는 것 같지만 새 서비스 설정에 여전히 가끔 문제가 있습니다. 나는 더 표준적인 초기화 스크립트가 왜 오작동하는지 알아내는 중이기 때문에 덕트 테이프를 고치고 와이어 솔루션을 묶는 데 별로 관심이 없습니다.
어떤 아이디어가 있나요?
내 이전 초기화 스크립트는 다음과 같습니다.
#! /bin/sh
### BEGIN INIT INFO
# Provides: myd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Initscript for myService daemon
### END INIT INFO
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="myService daemon"
NAME=myd
DAEMON=/home/uname/myService/bin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
start-stop-daemon --start --quiet \
--background \
--pidfile $PIDFILE \
--make-pidfile \
--user uname \
--chuid uname \
--startas /bin/bash \
--test \
-- -c "exec $DAEMON >> /.myd/var/init.log 2>&1" \
|| return 1
start-stop-daemon --start --quiet \
--background \
--pidfile $PIDFILE \
--make-pidfile \
--user uname \
--chuid uname \
--startas /bin/bash \
-- -c "exec $DAEMON >> /home/uname/.myd/var/init.log 2>&1" \
|| return 2
# Add code here, if necessary, that waits for the process to be ready
# to handle requests from services started subsequently which depend
# on this one. As a last resort, sleep for some time.
return 0
}
#
# Function that stops the daemon/service
#
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# 2 if daemon could not be stopped
# other if a failure occurred
start-stop-daemon --stop --quiet \
--retry=TERM/30/KILL/5 \
--pidfile $PIDFILE \
--name $NAME
RETVAL="$?"
[ "$RETVAL" = 2 ] && return 2
# Wait for children to finish too if this is a daemon that forks
# and if the daemon is only ever run from this initscript.
# If the above conditions are not satisfied then add some other code
# that waits for the process to drop all resources that could be
# needed by services started subsequently. A last resort is to
# sleep for some time.
start-stop-daemon --stop --quiet --oknodo \
--retry=0/30/KILL/5 \
--exec $DAEMON
[ "$?" = 2 ] && return 2
# Many daemons don't delete their pidfiles when they exit.
rm -f $PIDFILE
return "$RETVAL"
}
#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
#
# If the daemon can reload its configuration without
# restarting (for example, when it is sent a SIGHUP),
# then implement that here.
#
start-stop-daemon --stop --signal 1 --quiet \
--pidfile $PIDFILE \
--name $NAME
return 0
}
case "$1" in
start)
log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) log_end_msg 0
;;
2) log_end_msg 1
;;
esac
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) log_end_msg 0
;;
2) log_end_msg 1
;;
esac
;;
status)
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
;;
#reload|force-reload)
#
# If do_reload() is not implemented then leave this commented out
# and leave 'force-reload' as an alias for 'restart'.
#
#log_daemon_msg "Reloading $DESC" "$NAME"
#do_reload
#log_end_msg $?
#;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
exit 3
;;
esac
:
나의 새로운 (투박한) 스크립트는 (주로) 작동합니다:
#! /bin/sh
### BEGIN INIT INFO
# Provides: myd
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Initscript for myService daemon
### END INIT INFO
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="myService daemon"
NAME=myd
DAEMON=/home/uname/myService/bin/$NAME
DAEMON_ARGS=""
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
#
# Function that starts the daemon/service
#
do_start()
{
(
runuser -l uname "$DAEMON" >/dev/null 2>&1 &
echo "$!" > "$PIDFILE"
)
return 0
}
#
# Function that stops the daemon/service
#
do_stop()
{
PID="$(cat $PIDFILE)"
kill "$PID" >/dev/null 2>&1
#Give myd 5 seconds for an orderly shutdown
for i in $(seq 1 5); do
sleep 1
if [ ! kill -0 "$PID" >/dev/null 2>&1 ]; then
rm "$PIDFILE"
return 0;
fi
done
#No more playing nice: KILL THE DAEMON
if [ kill -0 "$PID" >/dev/null 2>&1 ]; then
echo "Orderly shutdown failed, sending kill signal"
kill -9 "$PID" >/dev/null 2>&1
fi
#Give myd 5 more seconds then fail
for i in $(seq 1 5); do
sleep 1
if [ ! kill -0 "$PID" >/dev/null 2>&1 ]; then
rm "$PIDFILE"
return 0;
fi
done
#FAILED
echo "Failed to kill $DESC $NAME"
return 1
}
case "$1" in
start)
echo "Starting $DESC $NAME" >&2
do_start
;;
stop)
echo "Stopping $DESC $NAME" >&2
do_stop
;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
echo "Restarting $DESC $NAME" >&2
do_stop
do_start
;;
*)
#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
:
그런데, 많은 인터넷 검색과 골치 아픈 노력 끝에 나는 여전히 종속성 시작 등을 위한 새로운 시스템을 잘 이해하지 못합니다. 내가 좀 더 잘 배울 수 있도록 누군가 나에게 일부 (현재) 문서의 방향을 알려줄 수 있습니까? 나는 내가 사용하고 있는 시스템에 대해 아무것도 모르는 것을 싫어한다.
감사해요!
답변1
init 스크립트가 매우 일반적이므로 기본 systemd 단위로 변환하는 것을 고려해야 합니다. 예를 들어 데몬이 실행 중인지 확인하는 PIDFILE이 있으므로 중지 코드를 완전히 제거하고 systemd의 기본 메커니즘이 작동하도록 할 수 있습니다. 죽이는 방법을 알아두세요(참고자료 참조 man systemd.kill
).
systemd는 학습 곡선이 크지만 다음과 같이 시작할 수 있습니다.이 블로그Lennart Poettering이 직접 systemd로 변환했습니다.
일반적으로 내장된 시스템 호환성으로 인해 초기화 스크립트는 계속 작동해야 합니다. man systemd-sysv-generator
스크립트에 대한 시스템 단위 파일 래퍼를 찾아서 찾으세요 .myd
/run/systemd/generator.late/myd.service
스크립트 상태 및 로그 확인
sudo systemctl status myd
비슷한 방식으로 중지하고 시작합니다. 참고하세요덫나는 그것을 설명했다.이 답변systemd가 이미 시작했다고 생각하는 것을 두 번째로 시작하면 아무런 효과가 없습니다.
바라보다이 위키System V 또는 귀하와 같은 시작 스크립트를 기본 시스템 단위로 변환하는 데 사용됩니다.