web-dev-qa-db-ja.com

シェルスクリプトをsystemdの制御下に置く

私がこのようなシェルスクリプトを持っていると仮定します:

#!/bin/sh
# cherrypy_server.sh

PROCESSES=10
THREADS=1 # threads per process
BASE_PORT=3035 # the first port used
# you need to make the PIDFILE dir and insure it has the right permissions
PIDFILE="/var/run/cherrypy/myproject.pid"
WORKDIR=`dirname "$0"`
cd "$WORKDIR"

cp_start_proc()
{
 N=$1
 P=$(( $BASE_PORT + $N - 1 ))
 ./manage.py runcpserver daemonize=1 port=$P pidfile="$PIDFILE-$N" threads=$THREADS request_queue_size=0 verbose=0
}

cp_start()
{
 for N in `seq 1 $PROCESSES`; do
  cp_start_proc $N
 done
}

cp_stop_proc()
{
 N=$1
 #[ -f "$PIDFILE-$N" ] && kill `cat "$PIDFILE-$N"`
 [ -f "$PIDFILE-$N" ] && ./manage.py runcpserver pidfile="$PIDFILE-$N" stop
 rm -f "$PIDFILE-$N"
}

cp_stop()
{
 for N in `seq 1 $PROCESSES`; do
  cp_stop_proc $N
 done
}

cp_restart_proc()
{
 N=$1
 cp_stop_proc $N
 #sleep 1
 cp_start_proc $N
}

cp_restart()
{
 for N in `seq 1 $PROCESSES`; do
  cp_restart_proc $N
 done
}

case "$1" in
 "start")
  cp_start
 ;;
 "stop")
  cp_stop
 ;;
 "restart")
  cp_restart
 ;;
 *)
  "$@"
 ;;
esac

Bashスクリプトから、本質的に3つのことを実行できます。

  1. ./cherrypy_server.sh startを呼び出して、cherrypyサーバーを起動します
  2. ./cherrypy_server.sh stopを呼び出して、cherrypyサーバーを停止します
  3. ./cherrypy_server.sh restartを呼び出して、cherrypyサーバーを再起動します

このシェルスクリプトをsystemdの制御下にcherrypy.serviceファイルとして配置するにはどうすればよいですか(マシンの再起動時にsystemdがcherrypyサーバーを起動するという明確な目標があります)?

参照systemdサービスファイルの例- https://wiki.archlinux.org/index.php/Systemd#Using_service_file

6
Calvin Cheng

私はSick BeardとSabNZBdの2つのpython/cherrypyアプリにそれらを使用します。違いは、「フォーク」をいつ使用するかを知っていることです。これは基本的にsystemdにメインバイナリがフォークするため、ファイルからPIDを推測する必要があることを伝えます。 WantedByは、これを開始するために必要なターゲットを定義するためのものであり、ランレベルと見なします。また、2番目の定義は、起動情報を保持するためにディレクトリを使用することにも気づくでしょう。これは、開始されたデーモンごとに$process-$portを作成するためです(異なるポートでメインのデーモンによって生成される多くのデーモンがある場合があります)。

IMOでは、ExecStartにスクリプトを追加し、それがforkingであることを確認して、メインのPIDファイル、または少なくとも「これが停止している場合はサービスを再起動する」ことを意味するPIDファイルを見つける方法を追加できます。

たぶん理想は、デーモンごとに「シンプル」な1つのサービスファイルを作成することでしょうか。

[Unit]
Description=Internet PVR for your TV Shows
After=cryptsetup.target

[Service]
ExecStart=/usr/bin/python2 /path/to/Sick-Beard/SickBeard.py
Type=simple
User=<user under which to run>
Group=<group of said user>

[Install]
WantedBy=multi-user.target

そして、これは分岐したものです

[Unit]
Description=Binary Newsreader
After=cryptsetup.target

[Service]
ExecStart=/usr/bin/python2 /path/to/sabnzbd/SABnzbd.py -d -f /path/to/inifile --pid /run/sabnzbd
Type=forking
PIDFile=/run/sabnzbd/sabnzbd-8080.pid
User=<user to run the process>
Group=<group of said user>

[Install]
WantedBy=multi-user.target
6
coredump