macOSにはサービスを自動起動するために launchctl という機構があります。 10年前にApacheの設定をした ときから気づいてはいたのですが、使ってみることはありませんでした。 今回 MacBook でも Nginx を動かそうかと思っているので、その予行演習として、Node製のサービスを自動起動してみます。
使い方は Linux の systemctl に似ています。 launchd.plist と呼ばれる起動方法を記述したXMLファイルを launchctl に読み込ませると launchd が自動起動するようになるという機構です。 systemd.unit と呼ばれる設定ファイルを systemctl で読み込むと systemd によって自動起動される Linux の機構と同じですね。
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
}
ということですね。
Label と ProgramArguments は必須です。 他にもプロパティは定義されているので、詳しく知りたければ man 5 launchd.plist でドキュメントが参照できます。
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 参照。
man 8 launchd より。
配置場所 | 説明 |
---|---|
~/Library/LaunchAgents | 各ユーザ管理の定期起動サービス |
/Library/LaunchAgents | 管理者管理の定期起動サービス |
/Library/LaunchDaemons | 管理者管理の常駐サービス |
/System/Library/LaunchAgents | OS管理の定期起動サービス |
/System/Library/LaunchDaemons | OS管理の常駐サービス. |
定期起動サービスと常駐サービスの違いがよくわかりませんが、各ユーザが作ったサービスは ~/Library/LaunchAgents
に置くので定期起動サービスの扱いになります。
もっともログインすれば必ず起動しているので、ユーザからしてみれば常駐サービスと同じです。
Node製のサービス LiuLian を「ユーザ管理」で常駐させます。 ログイン時に起動し、ログアウト時に停止する使い方です。
ローカルディレクトリに 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。