私がサポートするLinuxサービスがあります。一般的に使用されるstart
コマンドを提供しますstop
。デザイナーは、メイン機能の開始と再試行を制御するように設計されたラッパーコマンドを作成しました。ラッパーには、pidofproc
自分自身を呼び出してすでに実行されていることを確認する初期チェックが含まれています。開始および停止機能もこれを確認するために使用されます。
pidofprocを呼び出した後、pidofprocを使用するinit.dプログラムの起動および停止機能には問題はありませんが、. /etc/init.d/functions
ラッパーは同じように見える操作を実行できません。
もともと包装紙でいくつかの問題を発見しました。最初は呼び出さなかったfunctions
。その後、戻り値を文字列として正しくテストしませんでした。また、サービススクリプトがbashスクリプトで、ラッパーがシェルであることを確認してbashに切り替えました。これらのどれも役に立ちません。
問題のMCVEを作成しました。ラッパーは実行を維持するために役に立たないwhileループを実行しますが、実際のコードと非常によく似ています。問題は、myprog
すでに実行されているインスタンスがあるときに実行している場合、関数__pids_pidof
の関数がから戻り値を取得できないpidof
のに対し、起動スクリプトと停止スクリプトが正しく機能することをトレースで明確に示すことです。
違いは何ですか?
ラッパースクリプトの例 /usr/sbin/safe_myprog:
#!/bin/bash
set -x
PROG_NAME=myprog
INSTALL_DIR=/var/www/${PROG_NAME}
PROG=${INSTALL_DIR}/bin/${PROG_NAME}
SAFE_PROG_NAME=safe_myprog
SAFE_MYPROG=/usr/sbin/${SAFE_PROG_NAME}
message() {
# echo "$1" >&2
logger -t safe_myprog[$$] "$1"
}
. /etc/init.d/functions
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "$safe_myprog" ]; then
if [ -n "$(ps -p $safe_myprog -o pid=)" ]; then
message "$SAFE_PROG_NAME: is already running. pid: $safe_myprog"
exit 0
fi
fi
while :; do
sleep 60
done
サービスプログラム/etc/init.d/myprog:
#!/bin/bash
set -x
# Source function library.
. /etc/init.d/functions
cd /
PROG_NAME=myprog
INSTALL_DIR=/var/www/${PROG_NAME}
SAFE_PROG_NAME=safe_myprog
SAFE_MYPROG=/usr/sbin/${SAFE_PROG_NAME}
PROG=${INSTALL_DIR}/bin/${PROG_NAME}
PROG_LOCK_FILE=/var/lock/subsys/${PROG_NAME}
PROG_PID_FILE=/var/lib/${PROG_NAME}/${PROG_NAME}.pid
RETVAL=0
txtgrn=$(tput setaf 2)
txtred=$(tput setaf 1)
txtrst=$(tput sgr0)
message() {
if [ $RETVAL -eq 0 ]; then
printf "%-45s[${txtgrn} OK ${txtrst}]\n" "$1"
else
printf "%-45s[${txtred}FAILED${txtrst}]\n" "$1"
fi
}
start() {
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "${safe_myprog}" ]; then
message $"$SAFE_PROG_NAME: is already running. pid: $safe_myprog"
return 0
fi
#$SAFE_MYPROG > /dev/null 2>&1
$SAFE_MYPROG &
RETVAL=$?
message $"Starting $PROG_NAME: "
if [ $RETVAL -eq 0 ]; then
touch $PROG_LOCK_FILE
fi
return $RETVAL
}
stop() {
safe_myprog=`pidofproc $SAFE_MYPROG`
if [ -n "${safe_myprog}" ]; then
/bin/kill $safe_myprog
fi
if [ -e $PROG_PID_FILE ]; then
pid=$(cat $PROG_PID_FILE)
if [ -n "$(ps -p $pid -o pid=)" ]; then
/bin/kill -9 "$pid"
RETVAL=$?
#if [ $# -eq 0 ]; then
message "Stopping $PROG_NAME: pid: $pid"
#fi
else
#if [ $# -eq 0 ]; then
message "$PROG_NAME is already stopped."
#fi
/bin/rm -f $PROG_PID_FILE
RETVAL=0
fi
fi
if [ -f $PROG_PID_FILE ]; then
/bin/rm -f $PROG_PID_FILE
fi
if [ -e $PROG_LOCK_FILE ]; then
/bin/rm -f $PROG_LOCK_FILE
fi
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
esac
exit $RETVAL
この操作を 2 回実行したservice myprog start
後に safe_myprog を直接実行すると、safe_myprog トレース出力の主な部分は次のとおりです。
++ __pids_pidof /usr/sbin/safe_myprog
++ pidof -c -m -o 14454 -o 30619 -o %PPID -x /usr/sbin/safe_myprog
++ pidof -c -m -o 14454 -o 30619 -o %PPID -x safe_myprog
++ return 3
+ safe_myprog=
+ '[' -n '' ']'
startへの2番目の呼び出しは同じ関数呼び出しの出力であるように見えますが、次のようになります。
++ __pids_pidof /usr/sbin/safe_myprog
++ pidof -c -m -o 14406 -o 14399 -o %PPID -x /usr/sbin/safe_myprog
+ safe_myprog=14339
+ '[' -n 14339 ']'
+ message 'safe_myprog: is already running. pid: 14339'
pidof -c -m -o 14454 -o 30619 -o %PPID -x /usr/sbin/safe_myprog
コマンドラインから実行すると(実行後functions
)正解が与えられます。
この関数を使用するラッパーシェルは、この関数を使用するinit.dシェルとどのように比較され、具体的にpidofproc
なぜpidof
他の答えを提供するのでしょうか。