macOSにはサービスを自動起動するために launchctl という機構があります。10年前にApacheの設定をした ときから気づいてはいたのですが、使ってみることはありませんでした。今回 MacBook でも Nginx を動かそうかと思っているので、その予行演習として、Node製のサービスを自動起動してみます。
launchctl の使い方
使い方は Linux の systemctl に似ています。launchd.plist と呼ばれる起動方法を記述したXMLファイルを launchctl に読み込ませると launchd が自動起動するようになるという機構です。systemd.unit と呼ばれる設定ファイルを systemctl で読み込むと systemd によって自動起動される Linux の機構と同じですね。
launchd.plist の記述法
Apacheの launchd.plist は /System/Library/LaunchDaemons/org.apache.httpd.plist
にあります。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabled</key> <true/> <key>Label</key> <string>org.apache.httpd</string> <key>EnvironmentVariables</key> <dict> <key>XPC_SERVICES_UNAVAILABLE</key> <string>1</string> <key>OBJC_DISABLE_INITIALIZE_FORK_SAFETY</key> <string>YES</string> </dict> <key>ProgramArguments</key> <array> <string>/usr/sbin/httpd-wrapper</string> <string>-D</string> <string>FOREGROUND</string> </array> <key>KeepAlive</key> <true/> </dict> </plist>
XMLなので非常に冗長ですが、JSONで表現すれば、
{ "Disabled": true, "Label": "org.apache.httpd", "EnvironmentVariables": { "XPC_SERVICES_UNAVAILABLE": "1", "OBJC_DISABLE_INITIALIZE_FORK_SAFETY": "YES" }, "ProgramArguments": [ "/usr/sbin/httpd-wrapper", "-D", "FOREGROUND" ], "KeepAlive": true }
ということですね。
- Disabled
- サービスを強制的にロードするとき false に設定する。省略した場合のデフォルト値は false。*1
- Label
- launchd に対する一意なサービス名*2を指定する。
- EnvironmentVariables
- サービス起動時に設定する環境変数。
- ProgramArguments
- サービスの起動引数。
- KeepAlive
- サービスを常駐させるとき true に設定する。*3
Label と ProgramArguments は必須です。他にもプロパティは定義されているので、詳しく知りたければ man 5 launchd.plist でドキュメントが参照できます。
launchctl の使用例
launchctl の使用例をいくつか見てみましょう。
$ launchctl load service.plist
ファイル名を指定してサービスを launchctl の管理下に置く。KeepAlive に true を指定したサービスはこの瞬間に起動されます。
$ launchctl start label
サービス名を指定してサービスを起動する。
$ launchctl stop label
サービス名を指定してサービスを(一時)停止する。KeepAlive に true を指定したサービスはOS再起動時に再起動されるので一時停止です。
$ launchctl unload service.plist
ファイル名を指定してサービスを launchctl の管理下から外す。KeepAlive に true を指定したサービスはこれで起動されなくなります。
詳細は man launchctl 参照。
launchd.plist の配置場所
man 8 launchd より。
配置場所 | 説明 |
---|---|
~/Library/LaunchAgents | 各ユーザ管理の定期起動サービス |
/Library/LaunchAgents | 管理者管理の定期起動サービス |
/Library/LaunchDaemons | 管理者管理の常駐サービス |
/System/Library/LaunchAgents | OS管理の定期起動サービス |
/System/Library/LaunchDaemons | OS管理の常駐サービス. |
定期起動サービスと常駐サービスの違いがよくわかりませんが、各ユーザが作ったサービスは ~/Library/LaunchAgents
に置くので定期起動サービスの扱いになります。もっともログインすれば必ず起動しているので、ユーザからしてみれば常駐サービスと同じです。
実際に動かしてみる
Node製のサービス LiuLian を「ユーザ管理」で常駐させます。ログイン時に起動し、ログアウト時に停止する使い方です。
plistの記述
ローカルディレクトリに net.kobalab.liulian.plist
の名称で以下の内容のファイルを作成しました。ファイル名はサービス名に合わせる流儀のようです。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Disabled</key> <true/> <key>Label</key> <string>net.kobalab.liulian</string> <key>ProgramArguments</key> <array> <string>/opt/homebrew/bin/node</string> <string>/opt/homebrew/bin/liulian</string> <string>/Users/koba/Work/LiuLian/</string> </array> <key>KeepAlive</key> <true/> </dict> </plist>
ログインシェルが設定する PATH は使えないので、コマンド名などはフルパスで記述します*4。
起動
作成した plist を ~/Library/LaunchAgents
に配置します。
$ mv net.kobalab.liulian.plist ~/Library/LaunchAgents
すると以下の通知が現れます。これだけで load されたようです。
この後は システム設定 → 一般 → ログイン項目 で操作できるようになります*5。