Warning message

This translation is outdated. For the most up-to-date information, please refer to the English version.

init スクリプトを systemd unit ファイルに変換する

Solution In Progress - Updated -

Environment

  • Red Hat Enterprise Linux 7

Issue

  • Red Hat Enterprise Linux 6 以前のバージョンの init スクリプトを systemd unit ファイルに移植して Red Hat Enterprise Linux 7 以降で動くようにするには
  • init スクリプトを systemd unit ファイルに変換するには
  • カスタムの init スクリプトを変更して systemd と互換性を持たせるには

Resolution

以下の情報は例として提供されるものであり、すべての状況で正しく動作することが保証されているわけではありません。Red Hat サポートは、unit ファイルの設定と構文に関する質問にはお答えできますが、移植されるスクリプトを提供することは弊社のサポート対象外となります。

Red Hat Enterprise Linux 7 で管理されているすべてのパッケージは、systemd がすでに動作している状態でインストールされます。Red Hat Enterprise Linux 7 で実行することが認定されているソフトウェアを提供しているすべてのサードパーティは、Red Hat Enerprise Linux 7 の systemd unit ファイルを含めて提供すべきであるということになります。サードパーティソフトウェアプロバイダに確認することなくお客様独自に init スクリプトを移植することは行わないでください。事前にサードパーティソフトウェアプロバイダに確認の上、適切な unit ファイルの提供を依頼してください。

以下の例では、簡易的なデーモンをコンパイルして、そのデーモンの init スクリプトを作成します。その後、init スクリプトを systemd unit ファイルに移植します。

I. Hello World のデーモン

RHEL 6 システムを起動して、以下のように、gcc、lsof、wget、および telnet クライアントをインストールします。

yum install gcc lsof wget telnet 

次に、以下から取得したものを使用して簡易的なデーモンを作成します。以下で提供されるデーモンは単なる例であり、サポート対象外となりますが、使用することはできます。

http://www.catb.org/esr/cookbook/helloserver.c

このデーモンはポート 30153 でリッスンし、入力したものをエコーバックした後、接続を閉じて引き続き実行します。以下のコマンドでデーモンを作成します。

wget http://www.catb.org/esr/cookbook/helloserver.c
gcc -o hellod helloserver.c
sudo mv hellod /usr/local/bin/

デーモンを起動します。

/usr/local/bin/hellod 

実行していることを確認し、PID を取得します。

[root@rhel6 hello]# ps axu | grep hellod
root      2893  0.0  0.1   6164   584 ?        S    14:21   0:00 /usr/local/bin/hellod
root      2895  0.0  0.1 103244   828 pts/0    S+   14:21   0:00 grep hellod
[root@rhel6 hello]# 

そのプロセスがどのファイルを開いているかを確認します。

[root@rhel6 hello]# lsof -p 2893
COMMAND  PID USER   FD   TYPE             DEVICE SIZE/OFF   NODE NAME
hellod  2893 root  cwd    DIR              253,0     4096      2 /
hellod  2893 root  rtd    DIR              253,0     4096      2 /
hellod  2893 root  txt    REG              253,0    17468 145414 /usr/local/bin/hellod
hellod  2893 root  mem    REG              253,0    65928 133364 /lib64/libnss_files-2.12.so
hellod  2893 root  mem    REG              253,0  1921216 133348 /lib64/libc-2.12.so
hellod  2893 root  mem    REG              253,0   154520 133336 /lib64/ld-2.12.so
hellod  2893 root    0u   CHR                1,3      0t0   3782 /dev/null
hellod  2893 root    1u   CHR                1,3      0t0   3782 /dev/null
hellod  2893 root    2u   CHR                1,3      0t0   3782 /dev/null
hellod  2893 root    3u   REG              253,0        5     80 /var/run/helloserver.pid
hellod  2893 root    4u  unix 0xffff88001de616c0      0t0  18774 socket
hellod  2893 root    5u  IPv4              18775      0t0    TCP *:30153 (LISTEN)
[root@rhel6 hello]# 

デーモンをテストします。

[root@rhel6 hello]# telnet localhost 30153
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
hello
Connection closed by foreign host.
[root@rhel6 hello]# 

デーモンを kill して、クリーンアップされたことを確認します。

[root@rhel6 hello]# ls /var/run/ | grep hello
helloserver.pid
[root@rhel6 hello]# kill 2893
[root@rhel6 hello]# ls /var/run/ | grep hello
[root@rhel6 hello]# 

これで、init スクリプトを作成するためのデーモンが作成できました。

II. RHEL 6 の Hello World 用 System V Init スクリプト

次に、hellod の init スクリプトを作成します。

touch /etc/init.d/hello 
chmod 755 /etc/init.d/hello 

以下の行を /etc/init.d/hello に追加します。

#!/bin/bash
#
# chkconfig: 35 90 12
# description: Hello Daemon

以下は注意点になります。

  • chckconfig 行を追加すると、chckconfig コマンドでスクリプトを管理できます。
  • 35 は、ランレベル 3 および 5 で起動することを示しています。
  • 90 は起動優先度です (最後のサービスの一つが起動します)。
  • 12 は kill する順番です (最初のサービスの一つが kill されます)。

次に、以下をその次の行に追加し、これ以降の手順で init スクリプトの残りの部分が include することになる functions の 800 行ファイルをここで include しておきます。

./etc/init.d/functions

その後、hellod サービスを起動する次の 8 行を追加します。success ファンクションは /etc/init.d/functions 中で定義されています。

start() {
        echo -n "Starting Hello Server: "
        /usr/local/bin/hellod 
        # touch the lock file
        touch /var/lock/subsys/hellod
        success $"Hello Server startup"
        echo
}

次に、hellod サービスを停止する以下の行を追加します。

stop() {
        echo -n "Stopping Hello Server: "
        killproc hellod
        # Remove the lock file
        rm -f /var/lock/subsys/hellod
        echo
}

最後に、入力が正しく処理され、start および stop ファンクションをコールするよう、以下の 18 行を追加します。killproc ファンクションは /etc/init.d/functions 中で定義されています。

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status servicename
        ;;
  restart|reload|condrestart)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload|status}"
        exit 1
esac

新しい init スクリプトを保存して、適切に動作することを確認します。

[root@rhel6 ~]# /etc/init.d/hello status
hellod is stopped
[root@rhel6 ~]# /etc/init.d/hello start
Starting Hello Server:                                     [  OK  ]
[root@rhel6 ~]# /etc/init.d/hello status
hellod (pid 3780) is running...
[root@rhel6 ~]# telnet localhost 30153
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello
hello
Connection closed by foreign host.
[root@rhel6 ~]# /etc/init.d/hello stop
Stopping Hello Server:                                     [  OK  ]
[root@rhel6 ~]# /etc/init.d/hello status
hellod is stopped
[root@rhel6 ~]# 

これで正しく動作する init スクリプトを作成できました。次に、init スクリプトが RHEL 7 で動作するように systemd に移植します。

III. RHEL7 の Hello World 用 Systemd Unit ファイル

/usr/local/bin/hellod のバイナリーを RHEL 6 から RHEL 7 に移動して、動作することを確認します。

unit ファイルを保存する /etc/systemd/system/hellod.service を作成します。パッケージメンテナーの unit ファイルは /usr/lib/systemd/system/ に存在する必要があり、systemd は /etc を優先するため、修正する場合は /etc/systemd/system/ にコピーする必要があります。

touch /etc/systemd/system/hellod.service
chmod 644 /etc/systemd/system/hellod.service

以下の 10 行を /etc/systemd/system/hellod.service に追加します。

[Unit]
Description=Hello Service
After=network.target

[Service]
ExecStart=/usr/local/bin/hellod
Type=forking
PIDFile=/var/run/helloserver.pid

[Install]
WantedBy=multi-user.target

上の 10 行を保存したら unit ファイルは終了です。詳細は、以下のようになります。

最初のセクションである [Unit] には、サービスの説明が含まれます。また、After= タイプの依存関係も設定されます。これは、サーバーでネットワークが実行されるまでこのネットワークサービスが起動しないことを意味します。

2 番目のセクション [Service] では、ExecStart= を使用して、サービスの起動時に実行するバイナリーへのパスを定義しています。元々のプログラムは forking デーモンであるため Type=forking を設定します。その他の種類については systemd.service の man ページを参照してください。forking を使用している場合は PIDFile= オプションを使用して、systemd がデーモンのメインプロセスを特定できるようにすることが推奨されます。上述の lsof の例では、デーモンによって作成された pid ファイルは /var/run/helloserver.pid でした。それを PIDFile= に明示的に設定します。

3 番目のセクション [Install] では WantedBy= を使用します。これは RHEL6 のランレベル 3 の状態であるマルチユーザーモードでサービスが起動しているべきであることを示しています。

systemd サービスファイルが作成できましたので、以下のコマンドを実行し、それが存在することを systemd に通知する必要があります。

systemctl daemon-reload

新しいサービスを開始します。

systemctl start hellod

テストします。

[root@rhel7 ~]# telnet localhost 30153
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hey
hey
Connection closed by foreign host.
[root@rhel7 ~]# 

ステータスを確認します。

[root@rhel7 ~]# systemctl status hellod
hellod.service - Hello Daemon
   Loaded: loaded (/etc/systemd/system/hellod.service; disabled)
   Active: active (running) since Mon 2014-06-16 17:15:57 EDT; 1min 38s ago
  Process: 11812 ExecStart=/usr/local/bin/hellod (code=exited, status=0/SUCCESS)
 Main PID: 11814 (hellod)
   CGroup: /system.slice/hellod.service
           └─11814 /usr/local/bin/hellod

Jun 16 17:15:57 rhel7.example.com systemd[1]: Starting Hello Daemon...
Jun 16 17:15:57 rhel7.example.com systemd[1]: Started Hello Daemon.
[root@rhel7 ~]# 

再起動すると PID が変更します。

[root@rhel7 ~]# systemctl restart hellod
[root@rhel7 ~]# systemctl status hellod
hellod.service - Hello Daemon
   Loaded: loaded (/etc/systemd/system/hellod.service; disabled)
   Active: active (running) since Mon 2014/06/16 17:23:54 EDT; 2s ago
  Process: 11898 ExecStart=/usr/local/bin/hellod (code=exited, status=0/SUCCESS)
 Main PID: 11900 (hellod)
   CGroup: /system.slice/hellod.service
           └─11900 /usr/local/bin/hellod

Jun 16 17:23:54 rhel7.example.com systemd[1]: Starting Hello Daemon...
Jun 16 17:23:54 rhel7.example.com systemd[1]: Started Hello Daemon.
[root@rhel7 ~]# 

デーモンを停止します。

systemctl stop hellod

基本的な init スクリプトを systemd に移植し、コードの 40 行を 10 行で上書きしました。サービスに対して systemd unit ファイルを書く際のより詳細な情報については systemd.service の man ページを参照してください。

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.