Bash
MacOSX
launchctl

macOSでBashスクリプトを常駐プロセスとしてログイン時に起動させる

More than 1 year has passed since last update.


はじめに

以前、下記の通り、ディレクトリを監視してGitにコミットするメールアドレスを変更するスクリプトを作成しました。

このスクリプトは非常に便利なので、忘れずに常に起動していてほしいと思っています。できればシステムの起動またはログインと同時に常駐プロセスとして起動したいですね。そこで今回は macOS でこのプログラムを常駐プロセスにする方法を検討します。


方針


LaunchAgents で起動する

macOSには launchd というサービス管理フレームワークが搭載されています。 launchdinitinetdcrond などの置き換えを目的としたもので、システム起動時やログイン時におけるプロセスの起動や定期実行を行うことができます。詳しい説明は他の記事に譲りますが、ここではユーザーレベルのプロセスの起動のためにはこの仕組みを利用するべきとだけ理解していただければ十分です。

launchd の設定ファイルは通称 launchd.plist と呼ばれます。 .plist はプロパティリストと呼ばれるmacOS全般で使われる設定ファイルの拡張子で、現在ではXML形式で記述されています。


実装

そんなこんなで、下記のようなプロパティリストを作成しました。このファイルを任意のファイル名(ここでは watch-git-email.plist )で ~/Library/LaunchAgents/ に保存してください。


~/Library/LaunchAgents/watch-git-email.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>Label</key>
<string>watch-git-email</string>
<key>ProgramArguments</key>
<array>
<string>/ABSOLUTE/PATH/TO/watch-git-email.sh</string>
<string>/ABSOLUTE/PATH/TO/PARENT/DIRECTROTY</string>
<string>expect-email@example.com</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

十分とは言えませんが、これで必要な項目は揃っています。簡単ですね。


実行

プロセスを起動させるためには下記のコマンドを実行します。 launchctllaunchd のための管理コマンドと理解しておけばだいたい大丈夫です。

$ launchctl load ~/Library/LaunchAgents/watch-git-email.plist

また、このディレクトリに保存しておけば、ログイン時に自動的にユーザー権限で実行されます。


停止

プロセスの停止には下記のコマンドを実行します。起動時との違いはサブコマンドが loadunload になるだけです。

$ launchctl unload ~/Library/LaunchAgents/watch-git-email.plist


解説


launchd.plist

設定ファイルの記述内容について軽く解説していきます。今回の目的に際してはこの程度の記述で実行できますが、もっと詳細に管理したいときは、ぜひlaunch.plistのマニュアルページでご確認ください。

launchd では登録されたプログラムを実行する単位を「ジョブ」と呼んでいます。ジョブ1つに対してプロパティリストが1つと考えてください。


ジョブの名称 - Label

ジョブには固有の名称をつける必要がありますので、これは必須項目です。この Label の値はファイル名と同一であることが期待されているようです。つまりファイル名は <Label>.plist ということですね。前述のファイルのファイル名もそのようになっていることに注目してください。

<key>Label</key>

<string>watch-git-email</string>


実行するコマンド - ProgramArguments

プログラムの実行方法を記述する項目です。コマンドと引数をそれぞれ配列の別要素として記述します。 $HOME などの環境変数には期待せず、絶対PATHを記載してください。相対PATHで記載する方法もありますが、ここでは単純化のためにこうしてください。引数を取らない場合は Program というkeyを使うことができ、当然ながら ProgramArgumentsProgram のどちらかが記載されている必要があります。

<key>ProgramArguments</key>

<array>
<string>/ABSOLUTE/PATH/TO/watch-git-email.sh</string>
<string>/ABSOLUTE/PATH/TO/PARENT/DIRECTROTY</string>
<string>expect-email@example.com</string>
</array>


ロード時に実行する - RunAtLoad

launchd がプロパティリストをロードした時に実行するか否かを指定します。デフォルトの挙動では launchd がロードした時にはジョブを登録するだけで、実行はしません。ロードした時に実行させたい場合は、この値を true にする必要があります。

crond のように定期実行させる場合には、ロード時には実行させる必要がないので、記載する必要はありません。(デフォルトの挙動になる)

<key>RunAtLoad</key>

<true/>


終わりに

launchd start というサブコマンドとか、保存するディレクトリによって起動するタイミングなどが違うといったことも説明したかったという気持ちもありますが、できるだけシンプルに説明するためにけっこうな部分を省きました。プログラムの自動起動が成功したら、改めて公式ドキュメントを読むことをおすすめします。