systemctlコマンドはsystemdやサービスマネージャの状態を確認でき、制御を行うことができます。
systemdはLinuxでのinitシステムの一つで、多くのLinuxディストリビューションではデフォルトで利用されています。
systemdはユニットファイルを利用して、サービスの制御をします。ユニットファイルを自作することもできますが、
インストールしたパッケージのサービスを利用する場合、基本的にsystemdのユニットファイルもインストールされるので、そのユニットファイルを利用して、systemctlコマンドでsystemdに対してそのサービスを起動させたり、自動起動の設定を行なったりできます。
目次
- 1 デフォルトのターゲットを確認(systemctl get-default)
- 2 サービスの状態を確認(systemctl status)
- 3 ユニットファイルの内容を確認(systemctl cat)
- 4 ユニットファイルのパラメータを確認(systemctl show)
- 5 ユニットファイルのドキュメントを表示(systemctl help)
- 6 サービスの起動(systemctl start)
- 7 サービスの停止(systemctl stop)
- 8 サービスの設定ファイルを再読み込み(systemctl reload)
- 9 サービスの自動起動の設定(systemctl enable)
- 10 サービスの自動起動の設定の解除(systemctl disable)
- 11 ユニットファイルの再読み込み(systemctl daemon-reload)
- 12 ユニットファイルの設定を編集(systemctl edit)
- 13 ユニットファイルのリストを確認(systemctl list-units等)
- 14 ユニットファイルの依存関係のリストを確認(systemctl list-dependencies)
- 15 ユニットファイルの検索パス
- 16 ユニットファイルを作成してユーザーサービスを起動
- 17 タイマーのユニットファイルを作成して定期的にサービスを実行
- 18 参考
デフォルトのターゲットを確認(systemctl get-default)
systemctl get-defaultはデフォルトのターゲットを確認することができます。
デフォルトのターゲットはマシンが起動するときに始めに読み込まれるsystemdのユニットファイルになります。
基本的に最初にデフォルトのターゲットで設定されているのはシステムサービスではgraphical.targetまたはmulti-user.targetであり、GUI環境ではgraphical.targetで、CUI環境ではmulti-user.targetになっていることが多いです。
コマンド例と実行結果
1 2 |
$ systemctl get-default graphical.target |
.targetファイルはユニットをグループ化したり、ユニットの同期ポイントとして利用されます。
graphical.targetは"Requires="でmulti-user.targetを依存関係として同時に起動するように要求して、
"After="でユニットの起動順としてmulti-user.targetの後にgraphical.targetが起動するようにされています。
graphical.target(#で始まる行はコメント)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ systemctl cat graphical.target # /lib/systemd/system/graphical.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Graphical Interface Documentation=man:systemd.special(7) Requires=multi-user.target Wants=display-manager.service Conflicts=rescue.service rescue.target After=multi-user.target rescue.service rescue.target display-manager.service AllowIsolate=yes |
multi-user.target(#で始まる行はコメント)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ systemctl cat multi-user.target # /lib/systemd/system/multi-user.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Multi-User System Documentation=man:systemd.special(7) Requires=basic.target Conflicts=rescue.service rescue.target After=basic.target rescue.service rescue.target AllowIsolate=yes |
systemdにはユーザーのログイン時に起動するユーザーサービスのためのデフォルトのターゲットも存在します。これは--userをつけることで確認できます。こちらはデフォルトの設定だとdefault.targetとなっています。
1 2 |
$ systemctl --user get-default default.target |
default.target
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ systemctl --user cat default.target # /usr/lib/systemd/user/default.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Main User Target Documentation=man:systemd.special(7) Requires=basic.target After=basic.target AllowIsolate=yes |
サービスの状態を確認(systemctl status)
systemctl statusはsystemdによって管理しているサービスの状態を確認することができます。
以下の例はnginxのサービス状態を確認したものになっています。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ systemctl status nginx.service ● nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: active (running) since Sat 2023-04-08 20:18:43 JST; 16h ago Docs: man:nginx(8) Process: 3225 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS) Process: 3226 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS) Main PID: 3311 (nginx) Tasks: 3 (limit: 2281) Memory: 3.9M CPU: 44ms CGroup: /system.slice/nginx.service ├─3311 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;" ├─3314 "nginx: worker process" └─3315 "nginx: worker process" 4月 08 20:18:43 ubuntu-VirtualBox systemd[1]: Starting A high performance web server and a reverse proxy server... 4月 08 20:18:43 ubuntu-VirtualBox systemd[1]: Started A high performance web server and a reverse proxy server. |
ユニットファイルの内容を確認(systemctl cat)
systemctl catはユニットファイルの内容を確認することができます。
また、最初の一行目にそのファイルの場所がコメントのように追加されるのが特徴的です。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ systemctl cat graphical.target # /lib/systemd/system/graphical.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Graphical Interface Documentation=man:systemd.special(7) Requires=multi-user.target Wants=display-manager.service Conflicts=rescue.service rescue.target After=multi-user.target rescue.service rescue.target display-manager.service AllowIsolate=yes |
ユニットファイルのパラメータを確認(systemctl show)
systemctl showはユニット、ジョブ、マネージャのパラメータを表示できます。
引数がない場合は、マネージャのパラメータを表示します。
例では表示される項目が多いため、最初の3行を表示しています。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 |
$ systemctl show | head -n3 Version=251.4-1ubuntu7 Features=+PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT -GNUTLS +OPENSSL +ACL +BLKID +CURL +ELFUTILS +FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP +LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +TPM2 +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -BPF_FRAMEWORK -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified Virtualization=oracle $ $ systemctl show graphical.target | head -n3 Id=graphical.target Names=graphical.target default.target runlevel5.target Requires=multi-user.target |
ユニットファイルのドキュメントを表示(systemctl help)
systemctl helpはユニットファイルに設定されているドキュメントを開くことができます。
コマンド例と実行結果
1 2 3 |
$ systemctl cat graphical.target | grep Doc Documentation=man:systemd.special(7) $ systemctl help graphical.target # manページが開きます。 |
サービスの起動(systemctl start)
systemctl startでサービスを起動できます。
コマンド例と実行結果
1 2 3 4 5 |
$ systemctl status nginx | grep 'Active' Active: inactive (dead) since Sun 2023-04-09 17:17:23 JST; 2s ago $ sudo systemctl start nginx $ systemctl status nginx | grep 'Active' Active: active (running) since Sun 2023-04-09 17:17:31 JST; 1s ago |
サービスの停止(systemctl stop)
systemctl stopでサービスを停止できます。
コマンド例と実行結果
1 2 3 4 5 |
$ systemctl status nginx | grep 'Active' Active: active (running) since Sun 2023-04-09 17:17:31 JST; 37min ago $ sudo systemctl stop nginx $ systemctl status nginx | grep 'Active' Active: inactive (dead) since Sun 2023-04-09 17:55:02 JST; 2s ago |
サービスの設定ファイルを再読み込み(systemctl reload)
systemctl reloadは指定したサービスが利用している設定ファイルを再読み込みすることができます。つまり、nginxのnginx.confやApacheのhttpd.conf等の設定ファイルを再読み込みできます。
コマンド例と実行結果
1 2 3 |
$ systemctl cat nginx | grep ExecReload= ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload $ sudo systemctl reload nginx |
サービスの自動起動の設定(systemctl enable)
systemctl enableはサービスの自動起動を出来るようにします。自動起動を設定するとLoadedの単純にdisabledになっている部分がenabledに変更されます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ systemctl cat nginx | grep -A1 'Install' [Install] WantedBy=multi-user.target $ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; disabled; preset: enabled) Active: inactive (dead) $ $ sudo systemctl enable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service. $ $ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: inactive (dead) |
自動起動の設定について、ユニットファイルのInstallセクションのWantedByの項目でsystemdに対してその項目と同時に起動するように要求します。
しかし、nginxはUnitセクションにAfterが設定されているため、自動起動をするときはそのタイミングまで起動を待ちます。
1 2 3 4 5 |
$ systemctl cat nginx | grep -A3 'Unit' #たまたまAfterが3行目だったので3 [Unit] Description=A high performance web server and a reverse proxy server Documentation=man:nginx(8) After=network.target nss-lookup.target |
systemctl enableは即時に起動させるコマンドではないため、自動起動の設定と同時に起動も行いたい場合は--nowオプションと同時に利用するか、その後にsystemctl startを行う必要があります。
1 |
sudo systemctl --now enable nginx |
または
1 2 |
sudo systemctl enable nginx sudo systemctl start nginx |
自動起動の設定と同時にサービスも起動
1 2 3 4 5 6 7 8 9 10 |
$ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; disabled; preset: enabled) Active: inactive (dead) $ sudo systemctl --now enable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service. $ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: active (running) since Mon 2023-04-10 15:44:00 JST; 2s ago |
サービスの自動起動の設定の解除(systemctl disable)
systemctl disableはsystemctl enableとはほぼ逆のコマンドになり、サービスの自動起動の設定の解除を行うことができます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 |
$ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: active (running) since Mon 2023-04-10 15:44:00 JST; 5min ago $ sudo systemctl disable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable nginx Removed "/etc/systemd/system/multi-user.target.wants/nginx.service". $ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; disabled; preset: enabled) Active: active (running) since Mon 2023-04-10 15:44:00 JST; 5min ago |
こちらもsystemctl enableと同様にサービスを停止させるコマンドではないため、同時にサービスの停止も行いたい場合は--nowオプションと同時に利用するか、その後にsystemctl stopを行う必要があります。
1 |
sudo systemctl --now disable nginx |
または
1 2 |
sudo systemctl disable nginx sudo systemctl stop nginx |
自動起動の設定の解除と同時にサービスの停止
1 2 3 4 5 6 7 8 9 10 |
$ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) Active: active (running) since Mon 2023-04-10 15:44:00 JST; 15min ago $ sudo systemctl --now disable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install disable nginx Removed "/etc/systemd/system/multi-user.target.wants/nginx.service". $ systemctl status nginx | grep -A1 'Loaded' Loaded: loaded (/lib/systemd/system/nginx.service; disabled; preset: enabled) Active: inactive (dead) |
ユニットファイルの再読み込み(systemctl daemon-reload)
systemctl daemon-reloadはユニットファイルの再読み込みを行って、systemdで管理している依存関係ツリーを再構築します。
systemdの管理しているユニットファイルとディスク上のユニットファイルに差が出ている場合に必要になります。
例えば、systemdの管理しているユニットファイルとディスク上のユニットファイルに差が出る例として、自動起動させているユニットファイルを編集するとこのコマンドが必要になるでしょう。
また、その場合だったら、systemctl daemon-reloadを実行するように注意文が出ます。
コマンド例と実行結果
1 2 3 4 5 6 7 8 9 10 11 |
$ sudo systemctl status nginx.service | head -n2 ○ nginx.service - A high performance web server and a reverse proxy server Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled) $ sudo vi /lib/systemd/system/nginx.service # Descriptionの最後に!を付けた $ sudo systemctl status nginx.service | head -n1 ○ nginx.service - A high performance web server and a reverse proxy server Warning: The unit file, source configuration file or drop-ins of nginx.service changed on disk. Run 'systemctl daemon-reload' to reload units. $ $ sudo systemctl daemon-reload $ sudo systemctl status nginx.service | head -n1 ○ nginx.service - A high performance web server and a reverse proxy server! |
ユニットファイルの設定を編集(systemctl edit)
systemctl editはユニットファイルを拡張または編集することができます。
オプションなしで利用するとエディタが開きます。その後、編集内容を保存したとき、ユニットファイルの設定の拡張ファイルとしてユニットファイルのある場所に'{UnitName}.d/override.conf'が作成されます。
この編集方法は、systemdのユニットファイルが自動生成されたもので、ユニットファイル自体を編集するのが不都合な場合に便利な設定方法になります。
コマンド例と実行結果
1 2 3 4 5 6 |
$ sudo systemctl edit snap.jenkins.jenkins.service Successfully installed edited file '/etc/systemd/system/snap.jenkins.jenkins.service.d/override.conf'. $ $ cat /etc/systemd/system/snap.jenkins.jenkins.service.d/override.conf [Service] Environment=JDK_JAVA_OPTIONS=-Dhudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT=true |
また、--fullオプションを用いるとユニットファイル自体を編集することができます。
1 2 |
$ sudo systemctl edit --full snap.jenkins.jenkins.service Successfully installed edited file '/etc/systemd/system/snap.jenkins.jenkins.service'. |
ユニットファイルのリストを確認(systemctl list-units等)
systemctl list-unitsはsystemdが現在メモリ内に持っているユニットのリストを確認できます。
例では行数が多かったため、最初の3行だけ表示しています。
コマンド例と実行結果
1 2 3 4 |
$ systemctl list-units | head -n3 UNIT LOAD ACTIVE SUB DESCRIPTION proc-sys-fs-binfmt_misc.automount loaded active running Arbitrary Executable File Formats File System Automount Point sys-devices-pci0000:00-0000:00:01.1-ata1-host0-target0:0:0-0:0:0:0-block-sr0.device loaded active plugged VBOX_CD-ROM |
他にも、list-automounts, list-sockets, list-timersもあります。
1 2 3 4 |
$ systemctl list-timers | head -n3 NEXT LEFT LAST PASSED UNIT ACTIVATES Mon 2023-04-10 16:33:08 JST 24min left Mon 2023-04-10 15:33:03 JST 35min ago anacron.timer anacron.service Mon 2023-04-10 18:16:56 JST 2h 8min left Mon 2023-04-10 13:18:24 JST 2h 50min ago fwupd-refresh.timer fwupd-refresh.service |
ユニットファイルの依存関係のリストを確認(systemctl list-dependencies)
systemctl list-dependenciesはユニットファイルの依存関係のリストを確認できます。
引数を省略するとdefault.targetが指定されます。
例では行数が多かったため、最初の3行だけ表示しています。
コマンド例と実行結果
1 2 3 4 |
$ systemctl list-dependencies | head -n3 default.target ● ├─accounts-daemon.service ● ├─apport.service |
--userをつけると違うユーザーサービスの別の依存関係を確認することができます。
1 2 3 4 |
$ systemctl --user list-dependencies | head -n3 default.target ● ├─pipewire-pulse.service ● ├─pipewire.service |
ユニットファイルの検索パス
ユニットファイルの検索パスは以下のmanページで確認できます。
1 |
man systemd.unit |
よく見るパスとしてはシステムのサービスマネージャだと
1 2 |
/etc/systemd/system/* /lib/systemd/system/* |
で、ユーザーのサービスマネージャだと
1 2 3 |
~/.config/systemd/user/* /etc/systemd/user/* /usr/lib/systemd/user/* |
かもしれません。
ユニットファイルを作成してユーザーサービスを起動
ここでは試しにシステムサービスではなくユーザーサービスを作成してみます。
単純なpythonプログラムのサービスを起動させるユニットファイルを作成して、その後、自動起動の設定を追加して行いたいと思います。
pythonプログラムは起動時の時間を覚えておき、5秒ごとに起動時までの経過した時間を表示する単純なプログラムになっています。
自動起動を行わないサービスの作成
まず自動起動を行わないユニットファイルを作成してみます。
作成する場所は~/.config/systemd/userとし、ファイル名はmyapp-sleep-print.serviceとします。
1 2 3 4 5 6 7 8 |
$ systemctl --user cat myapp-sleep-print.service # /home/ubuntu/.config/systemd/user/myapp-sleep-print.service [Unit] Description=python myapp sleep_print program [Service] Type=simple ExecStart=/home/ubuntu/myapp/sleep_print.py |
サービスに利用するプログラムを作成
pythonプログラムの方は以下のようになります。プログラムを作成した後は実行権限を付与することを忘れないようにしましょう。保存している場所は~/myappになり、ファイル名はsleep_print.pyになります。起動するプログラムは上のExecStartのパスと合わせましょう。また、ExecStartでパスを書く場合は基本的にフルパスである必要があります。
sleep_print.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/usr/bin/python3 import signal import sys import time def sigtermhandler(signum, frame): sys.exit(0) def sleep_print_main(): ssec = time.time() print(f"sleep start", flush=True) while True: time.sleep(5) print(f"sleep {time.time()-ssec:.2f} sec", flush=True) if __name__ == '__main__': signal.signal(signal.SIGTERM, sigtermhandler) try: sleep_print_main() finally: print("sleep end", flush=True) |
標準出力はsystemdで起動された場合、デフォルトではsystemdのロギングサービスのjournaldに渡されます。
簡単にプログラムの気になる点を解説します。
・print関数のflush=Trueは、文字の出力をバッファリングせずに即時に出力するために入れています。flush=Trueがないと文字の出力はバッファリングされ、journaldのログを確認しているときにプログラムの動作のタイミングと文字の出力の動作のタイミングが異なる感じになり、期待したタイミングで文字が出力されなくなる場合があります。
・signalの部分は、systemdがサービスを停止する場合、デフォルトではsystemdがそのサービスに対して、SIGTERMが送り、さらにその後にSIGKILLが送るそうですが、pythonプログラムはSIGTERMが送られるとtry-finallyのfinally部分を実行せずにプロセスを終了するそうなので、SIGTERMのシグナルをキャッチしたら、自分でプログラムを終了するような形にしてfinally部分が動作するようにしています。
print関数のflush=Trueが面倒なときは以下のようにprint関数をオーバーライドしてもいいかもしれません。
1 2 3 4 |
from functools import partial print = partial(print, flush=True) print("test") # デフォルトでflush=Trueとなる |
サービスの起動と停止
ユニットファイルとプログラムを作成したら、
1 |
$ systemctl --user start myapp-sleep-print.service |
で起動できます。
サービスを停止する場合は
1 |
$ systemctl --user stop myapp-sleep-print.service |
で停止することができます。
起動してから、20か30秒ぐらい経過した後に停止させた後にsystemctl statusを見ると以下のようなログを見ることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ systemctl --user status myapp-sleep-print.service ○ myapp-sleep-print.service - python myapp sleep_print program Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.service; static) Active: inactive (dead) 4月 10 16:15:16 ubuntu-VirtualBox systemd[1137]: Stopped python myapp sleep_print program. 4月 10 16:48:38 ubuntu-VirtualBox systemd[1137]: Started python myapp sleep_print program. 4月 10 16:48:39 ubuntu-VirtualBox sleep_print.py[8164]: sleep start 4月 10 16:48:44 ubuntu-VirtualBox sleep_print.py[8164]: sleep 5.01 sec 4月 10 16:48:49 ubuntu-VirtualBox sleep_print.py[8164]: sleep 10.01 sec 4月 10 16:48:54 ubuntu-VirtualBox sleep_print.py[8164]: sleep 15.01 sec 4月 10 16:48:59 ubuntu-VirtualBox sleep_print.py[8164]: sleep 20.02 sec 4月 10 16:49:01 ubuntu-VirtualBox sleep_print.py[8164]: sleep end 4月 10 16:49:01 ubuntu-VirtualBox systemd[1137]: Stopping python myapp sleep_print program... 4月 10 16:49:01 ubuntu-VirtualBox systemd[1137]: Stopped python myapp sleep_print program. |
また、GUI環境などではもう一つ端末を開いて、
1 |
journalctl --user -f -u myapp-sleep-print.service |
とするとリアルタイムでログを確認することができます。
自動起動の設定
Installセクションを追加します。ユーザーサービスなので、WantedByにdefault.targetを指定します。これがシステムサービスならば、graphical.targetやmulti-user.target等を指定するかもしれませんが、ユーザーサービスではそれらのシステムサービスのユニットファイルを指定できません。
1 2 3 4 5 6 7 8 9 10 11 |
$ systemctl --user cat myapp-sleep-print.service # /home/ubuntu/.config/systemd/user/myapp-sleep-print.service [Unit] Description=python myapp sleep_print program [Service] Type=simple ExecStart=/home/ubuntu/myapp/sleep_print.py [Install] WantedBy=default.target |
補足として、default.targetはユーザーサービスでユーザーログイン時に始めに読み込まれるユニットファイルになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ systemctl --user get-default default.target $ systemctl --user cat default.target # /usr/lib/systemd/user/default.target # SPDX-License-Identifier: LGPL-2.1-or-later # # This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. [Unit] Description=Main User Target Documentation=man:systemd.special(7) Requires=basic.target After=basic.target AllowIsolate=yes |
ユニットファイルができたら、systemctl enableで自動起動を設定します。
1 2 3 4 5 6 7 8 |
$ systemctl --user status myapp-sleep-print.service | grep -A1 'Loaded' Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.service; disabled; preset: enabled) Active: inactive (dead) $ systemctl --user enable myapp-sleep-print.service Created symlink /home/ubuntu/.config/systemd/user/default.target.wants/myapp-sleep-print.service → /home/ubuntu/.config/systemd/user/myapp-sleep-print.service. $ systemctl --user status myapp-sleep-print.service | grep -A1 'Loaded' Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.service; enabled; preset: enabled) Active: inactive (dead) |
ログアウトを行なって、再度ログインを行うと起動していることが確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
systemctl --user status myapp-sleep-print.service ● myapp-sleep-print.service - python myapp sleep_print program Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.servic> Active: active (running) since Mon 2023-04-10 19:48:30 JST; 20s ago Main PID: 9272 (sleep_print.py) Tasks: 1 (limit: 2281) Memory: 2.8M CPU: 30ms CGroup: /user.slice/user-1000.slice/[email protected]/app.slice/myapp-slee> └─9272 /usr/bin/python3 /home/ubuntu/myapp/sleep_print.py 4月 10 19:48:30 ubuntu-VirtualBox systemd[9265]: Started python myapp sleep_pr> 4月 10 19:48:30 ubuntu-VirtualBox sleep_print.py[9272]: sleep start 4月 10 19:48:35 ubuntu-VirtualBox sleep_print.py[9272]: sleep 5.00 sec 4月 10 19:48:40 ubuntu-VirtualBox sleep_print.py[9272]: sleep 10.01 sec 4月 10 19:48:45 ubuntu-VirtualBox sleep_print.py[9272]: sleep 15.01 sec 4月 10 19:48:50 ubuntu-VirtualBox sleep_print.py[9272]: sleep 20.01 sec |
サービスの停止と自動起動の設定を解除
最後に、今回試しに作ったサービスを停止し、また、このサービスは特に何も役に立たないので、自動起動の設定を解除して終わりにします。
1 2 3 4 5 6 7 8 9 10 11 |
$ systemctl --user status myapp-sleep-print.service | grep -A1 'Loaded' Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.service; enabled; preset: enabled) Active: active (running) since Mon 2023-04-10 19:59:37 JST; 56s ago $ $ systemctl --user disable myapp-sleep-print.service Removed "/home/ubuntu/.config/systemd/user/default.target.wants/myapp-sleep-print.service". $ systemctl --user stop myapp-sleep-print.service $ $ systemctl --user status myapp-sleep-print.service | grep -A1 'Loaded' Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-sleep-print.service; disabled; preset: enabled) Active: inactive (dead) |
タイマーのユニットファイルを作成して定期的にサービスを実行
タイマーのユニットファイルを作成すると定期的にサービスを実行することができます。
システムサービスでもタイマーで定期的にサービスを実行できますが、ここでは、試しにユーザーサービスでタイマーのユニットファイルを利用してみます。
タイマーで利用するサービスやプログラムを準備
タイマーで定期的に実行させるサービスは以下のようなものです。
1 2 3 4 5 6 7 8 |
$ systemctl --user cat myapp-rand-print.service # /home/ubuntu/.config/systemd/user/myapp-rand-print.service [Unit] Description=python myapp rand_print program [Service] Type=simple ExecStart=/home/ubuntu/myapp/rand_print.py |
また、利用するプログラムは以下のようなものになります。
~/myapp/rand_print.py
1 2 3 4 5 |
#!/usr/bin/python3 import random print(f"rand: {random.random() * 1000:.2f}") |
このプログラムをsystemctl startで起動させて、
1 |
$ systemctl --user start myapp-time-print.service |
その出力結果をjournalctlで確認すると以下のような感じになります。
1 2 3 |
$ journalctl --user -u myapp-rand-print.service 4月 11 20:38:15 ubuntu-VirtualBox systemd[9265]: Started python myapp rand_print program. 4月 11 20:38:15 ubuntu-VirtualBox rand_print.py[11440]: rand: 312.03 |
タイマーのユニットファイルを作成と起動の確認
タイマーのユニットファイルは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ systemctl --user cat myapp-rand-print.timer # /home/ubuntu/.config/systemd/user/myapp-rand-print.timer [Unit] Description=Run rand_print on Boot and every 10s [Timer] Unit=myapp-rand-print.service OnBootSec=5 OnUnitActiveSec=10 [Install] WantedBy=timers.target |
OnBootSecでまずマシンが起動してから5秒後にタイマーがサービスを1回起動させます。既に過ぎていた場合はタイマーはすぐにサービスを起動させます。その後のOnUnitActiveSecでタイマーがサービスを起動させた後の10秒後にまたタイマーがサービスを起動させます。こちらも既に過ぎていた場合はすぐに起動になります。
TimerセクションのUnitの指定はここでは必要ありませんが明示しています。これがない場合、タイマーが起動するサービスは同名のサービスのユニットファイルが指定されます。
タイマーのユニットファイルが作成出来た後は、自動起動を有効にします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ systemctl --user status myapp-rand-print.timer ○ myapp-rand-print.timer - Run rand_print on Boot and every 10s Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-rand-print.timer; disabled; preset: enabled) Active: inactive (dead) Trigger: n/a Triggers: ● myapp-rand-print.service $ $ systemctl --user enable myapp-rand-print.timer Created symlink /home/ubuntu/.config/systemd/user/timers.target.wants/myapp-rand-print.timer → /home/ubuntu/.config/systemd/user/myapp-rand-print.timer. $ $ systemctl --user status myapp-rand-print.timer ○ myapp-rand-print.timer - Run rand_print on Boot and every 10s Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-rand-print.timer; enabled; preset: enabled) Active: inactive (dead) Trigger: n/a Triggers: ● myapp-rand-print.service |
ユーザーサービスの起動タイミングはログイン時なので、一度ログアウトしてからもう一度タイマーのユニットファイルをsystemctl statusで確認すると起動していることが確認できます。
1 2 3 4 5 6 7 8 9 |
$ systemctl --user status myapp-rand-print.timer ● myapp-rand-print.timer - Run rand_print on Boot and every 10s Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-rand-print.timer; enabled; preset: enabl> Active: active (running) since Tue 2023-04-11 21:27:55 JST; 41s ago Until: Tue 2023-04-11 21:27:55 JST; 41s ago Trigger: n/a Triggers: ● myapp-rand-print.service 4月 11 21:27:55 ubuntu-VirtualBox systemd[12295]: Started Run rand_print on Boot and every 10s. |
その後、ある程度時間が経過した後にjournalctlでログを確認すると以下のようなログを確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$ journalctl --user -u myapp-rand-print.service 4月 11 20:38:15 ubuntu-VirtualBox systemd[9265]: Started python myapp rand_print program. 4月 11 20:38:15 ubuntu-VirtualBox rand_print.py[11440]: rand: 312.03 4月 11 21:27:55 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:27:55 ubuntu-VirtualBox rand_print.py[12303]: rand: 313.78 4月 11 21:28:05 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:28:05 ubuntu-VirtualBox rand_print.py[13070]: rand: 302.02 4月 11 21:28:16 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:28:16 ubuntu-VirtualBox rand_print.py[13208]: rand: 138.49 4月 11 21:28:36 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:28:36 ubuntu-VirtualBox rand_print.py[13242]: rand: 304.68 4月 11 21:29:00 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:29:00 ubuntu-VirtualBox rand_print.py[13249]: rand: 720.60 4月 11 21:29:42 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 21:29:42 ubuntu-VirtualBox rand_print.py[13391]: rand: 785.68 |
う~ん、微妙に精度が悪いですね。
時間の精度を細かくして再確認
調べてみるとTimerセクションのAccuracySecでタイマーの精度を設定できるそうです。デフォルトでは1分毎になっているので今回のものではタイマーの定期実行する時間の設定が短すぎたようです。
AccuracySecは電力消費を最適化するためにCPUのウェイクアップを抑えるために利用するそうです。今回は試しなのでこの時間精度の間隔を長くするのではなく、50msまで短くしたいと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ systemctl --user cat myapp-rand-print.timer # /home/ubuntu/.config/systemd/user/myapp-rand-print.timer [Unit] Description=Run rand_print on Boot and every 10s [Timer] Unit=myapp-rand-print.service OnBootSec=5 OnUnitActiveSec=10 AccuracySec=50ms [Install] WantedBy=timers.target |
ユニットファイルを編集したので、
1 |
$ systemctl --user daemon-reload |
をした後にタイマーをsystemctl startで起動させ、何十秒間待った後にjournalctlで確認してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ journalctl --user -u myapp-rand-print.service | tail -n 15 4月 11 22:02:21 ubuntu-VirtualBox rand_print.py[13720]: rand: 542.92 4月 11 22:02:31 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:02:31 ubuntu-VirtualBox rand_print.py[13723]: rand: 896.37 4月 11 22:02:41 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:02:41 ubuntu-VirtualBox rand_print.py[13724]: rand: 33.40 4月 11 22:02:52 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:02:52 ubuntu-VirtualBox rand_print.py[13725]: rand: 752.36 4月 11 22:03:02 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:03:02 ubuntu-VirtualBox rand_print.py[13728]: rand: 119.02 4月 11 22:03:12 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:03:12 ubuntu-VirtualBox rand_print.py[13733]: rand: 135.75 4月 11 22:03:22 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:03:22 ubuntu-VirtualBox rand_print.py[13736]: rand: 798.81 4月 11 22:03:32 ubuntu-VirtualBox systemd[12295]: Started python myapp rand_print program. 4月 11 22:03:32 ubuntu-VirtualBox rand_print.py[13737]: rand: 524.79 |
今度は良い感じのタイミングで定期的に実行しています。
サービスの停止と自動起動の設定の解除
最後に、今回試しに作ったサービスを停止して自動起動の設定を解除して終わりにします。
1 2 3 4 5 |
$ systemctl --user --now disable myapp-rand-print.timer Removed "/home/ubuntu/.config/systemd/user/timers.target.wants/myapp-rand-print.timer". $ systemctl --user status myapp-rand-print.timer | grep -A1 'Loaded' Loaded: loaded (/home/ubuntu/.config/systemd/user/myapp-rand-print.timer; disabled; preset: enabled) Active: inactive (dead) |
参考
ユニットファイルについては以下のmanページがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
$ whatis -w 'systemd*' |grep '(5)' systemd-sleep.conf (5) - Suspend and hibernation configuration file systemd-system.conf (5) - System and session service manager configuration files systemd-user-runtime-dir (5) - System units to start the user manager systemd-user.conf (5) - System and session service manager configuration files systemd.automount (5) - Automount unit configuration systemd.device (5) - Device unit configuration systemd.dnssd (5) - DNS-SD configuration systemd.exec (5) - Execution environment configuration systemd.kill (5) - Process killing procedure configuration systemd.link (5) - Network device configuration systemd.mount (5) - Mount unit configuration systemd.negative (5) - DNSSEC trust anchor configuration files systemd.netdev (5) - Virtual Network Device configuration systemd.network (5) - Network configuration systemd.path (5) - Path unit configuration systemd.positive (5) - DNSSEC trust anchor configuration files systemd.preset (5) - Service enablement presets systemd.resource-control (5) - Resource control unit settings systemd.scope (5) - Scope unit configuration systemd.service (5) - Service unit configuration systemd.slice (5) - Slice unit configuration systemd.socket (5) - Socket unit configuration systemd.swap (5) - Swap unit configuration systemd.target (5) - Target unit configuration systemd.timer (5) - Timer unit configuration systemd.unit (5) - Unit configuration $ whatis -w 'systemd*' |grep '(7)' systemd-stub (7) - A simple UEFI kernel boot stub systemd.directives (7) - Index of configuration directives systemd.environment-generator (7) - systemd environment file generators systemd.generator (7) - systemd unit generators systemd.index (7) - List all manpages from the systemd project systemd.journal-fields (7) - Special journal fields systemd.net-naming-scheme (7) - Network device naming schemes systemd.offline-updates (7) - Implementation of offline updates in systemd systemd.special (7) - Special systemd units systemd.syntax (7) - General syntax of systemd configuration files systemd.time (7) - Time and date specifications |