自作したシェルスクリプトを Linux の systemd サービスとして起動する方法
はじめに
最近は Kubernetes や サーバレス なしくみを用いたサービス運用が進んでいるため、Linux の Systemd を触る機会はほぼありません。
利用機会は今後どんどん減っていくとは思いますが、
担当しているサービスの一部で Google Compute Engine を利用しており、
Systemd を使ってシェルをサービス化する事があったので、エントリにまとめることにしました。
概要
当エントリでは、
Systemd をつかった Linux サーバー上が起動してたタイミングで、シェルスクリプトを自動的に実行する方法 について紹介します。
"Systemd" とは?
本当にかんたんに Systemd についてお話します。
Systemd は、 OS 起動後に起動する起動プロセスの 1 つです。
Systemd は 複数のアプリケーションを 子プロセス として起動します。
Systemd は常にプロセス ID が 1( PID=1 )となります。
古い Linux ディストリビューションではinitd という起動プラセスが担当していました、最近のディストリビューションではこれが Systemd に置きなおしされています。
とあるサーバで、 pstree
コマンドで PID=1 のプロセスの情報を表示してみます。
$ sudo pstree 1
systemd─┬─accounts-daemon─┬─{gdbus}
│ └─{gmain}
├─acpid
├─2*[agetty]
├─apache2───12*[apache2]
├─containerd─┬─containerd-shim─┬─mysqld───27*[{mysqld}]
│ │ └─10*[{containerd-shim}]
│ ├─2*[containerd-shim─┬─apache2───10*[apache2]]
│ │ └─10*[{containerd-shim}]]
│ ├─3*[containerd-shim─┬─httpd───4*[httpd───26*[{httpd}]]]
│ │ └─10*[{containerd-shim}]]
│ ├─4*[containerd-shim─┬─mysqld───35*[{mysqld}]]
│ │ └─10*[{containerd-shim}]]
│ ├─containerd-shim─┬─httpd───10*[httpd]
│ │ └─10*[{containerd-shim}]
│ └─25*[{containerd}]
├─cron
├─dbus-daemon
...
├─systemd───(sd-pam)
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─unattended-upgr───{gmain}
systemd は Linux オペレーションシステムでアプリケーションをサービスとして起動し、有効・無効を管理するためのアプリケーションです。
シェルスクリプトを systemd にサービスとして認識させる
まずはサービスとして登録したいシェルスクリプトを作成
早速自作のシェルスクリプトを systemd にサービスとして登録してみます。
今回作成するシェルスクリプトは、ディスクの使用情報のサマリ情報を定期的にログとして書き出すというものにします。
「監視日時」と「ディスク使用状況のサマリ」をそれぞれ 別の行で出力し、120 秒スリープしたら、まだ最初から処理を開始し直します。
#!/usr/bin/env bash
while :; do
date >>/var/log/storage-monitor.log
du --exclude=/proc -sch / >>/var/log/storage-monitor.log
sleep 120
done
このスクリプトをファイルに書き出し、実行権限を付与しておきます。
$ cat <<EOF >/usr/bin/script.sh
#!/usr/bin/env bash
while :; do
date >>/var/log/storage-monitor.log
du --exclude=/proc -sch / >>/var/log/storage-monitor.log
sleep 120
done
EOF
$ chmod +x /usr/bin/script.sh
サービスを作成する
次に、 Systemd に登録したいサービスを作成します。
「サービスを作成する」といっても、 /etc/systemd/system
というディレクトリにファイルを作成するだけです。
ファイル作成時は以下の点に注意しましょう。
- ファイル名は サービス名 とする
- ファイルの拡張子は
.service
とする
ファイルの中身は以下のような内容となります。
$ cat <<EOF >/etc/systemd/system/monitor-disk.service
[Unit]
Description=Disk monitoring shell script service
Documentation=
#After=networking.service
[Service]
Type=simple
User=root
Group=root
TimeoutStartSec=0
Restart=on-failure
RestartSec=30s
#ExecStartPre=
ExecStart=/usr/bin/script.sh
SyslogIdentifier=Diskutilization
#ExecStop=
[Install]
WantedBy=multi-user.target
EOF
# 内容を確認する
$ cat /etc/systemd/system/monitor-disk.service
[Unit]
Description=Disk monitoring shell script service
Documentation=
#After=networking.service
[Service]
Type=simple
User=root
Group=root
TimeoutStartSec=0
Restart=on-failure
RestartSec=30s
#ExecStartPre=
ExecStart=/usr/bin/script.sh
SyslogIdentifier=Diskutilization
#ExecStop=
[Install]
WantedBy=multi-user.target
いわゆる ini ファイル 形式のファイルです。
いちばん大事な点は以下になります。
User=root
: 実行ユーザ を指定Group=root
: 実行グループ を指定ExecStart=/usr/bin/script.sh
: 実行ファイル を指定
その他のフィールドについてもかんたんに説明します。
After
今回は利用していませんが、当サービス起動前に起動させておきたいサービス名を記述しておきます。
例えば、外部通信が必要なスクリプトの場合には、 After=networking.service
と記述します。
ExecStartPre
今回は利用しませんでしたが、
指定されていた場合は ExecStart
の処理が実行される前にこちらの処理が実行されます。
SyslogIdentifier
サービスのログは syslog 経由で出力されます。
syslog に出力されるログの各行に設定するプレフィックスとなります。
このプレフィックスを見れば、どのサービスのログかが特定しやすくなります。
systemctl
コマンドを使ってサービスの開始、有効化、無効化、停止、再起動を行う
「 サービスの作成 」が終了したら、サービスを管理する systemd に対して、開始や停止を 指示 します。
systemd に対してサービスの管理を指示するためには、 systemctl
コマンドを利用します。
サービスを開始
以下のコマンドでサービスを開始します。
$ systemctl start monitor-disk.service
スクリプトが正しく実行されていれば、スクリプトで生成されたログが確認できるはずです。
$ cat /var/log/storage-monitor.log
サービスの状態を確認
以下のコマンドでサービスの状態を確認します。
$ systemctl status monitor-disk.service
サービスが実行されているかを確認したり、出力されたログを確認することも可能です。
サーバ起動時に自動的にサービスを起動させる
このままではサーバ再起動が行われるたびに、手動でサービスを起動してやる必要があります。
これは面倒なので、サーバ起動時に自動的にサービスが起動されるようにしておきましょう。
$ systemctl enable monitor-disk.service
自動機能を無効にする場合は以下のコマンドを実行します。
$ systemctl disable monitor-disk.service
サービスを停止
停止は以下のコマンドです。
$ systemctl stop monitor-disk.service
サービスを再起動
再起動は以下のコマンドです。
$ systemctl reload monitor-disk.service
syslogについて
Systemd はデフォルトで syslog にログを書き出します。
したがって、リアルタイムのログを確認したい場合には以下のコマンドが利用できます。
$ tail -f /var/log/syslog
サービス設定ファイル( /etc/systemd/system/monitor-disk.service
)に SyslogIdentifier=Diskutilization
という設定を記述しておいたので、
キーワードで検索すれば当スクリプトのログだけに絞り込むことが可能でうs。
$ tail -f /var/log/syslog | grep Diskutilization
ひとこと
はじめにいったとおり、 Kubernetes や サーバレス なしくみを用いたサービス運用が進んでいるため、Linux の Systemd を触る機会は最近ほとんどありませんね。
ディスカッション
コメント一覧
まだ、コメントがありません