読者です 読者をやめる 読者になる 読者になる

launchd/launchctl に困った時

launchctl で上手く動いてくれないなあ、に困った時、とりあえずやってみると良かったと思ったこと。

Launch Button -- SMASH Rocket Club 5-9-09 4
Launch Button -- SMASH Rocket Club 5-9-09 4 / stevendepolo
  1. kick する実行ファイルに、実行権限があるか、を確認する。
    → 大概の問題はここ。
  2. plist、StandardOutPathStandardErrorPath key を挿し込んでみる。
    →何やってるか、どこで躓いてるか、を覗くことができる。
  3. launchctl のサブコマンド start を使う。
    →好きなタイミングでテストできる。

まずは、こんなトコかなと。

3 つめは、そんなにアレですかね。...かもしれません。う、

背景

前々から何となく気になっていた radiko の録音周り。
とあるキッカケをもって腹を決め、改めて手を入れることに。それはもう、結構肩までずっぽし突っ込んでゴッゾリほっくり返す。

で、このところ一応メドがついたので、気になったとこメモ。

今回は launchctl
録音処理の実行スケジューリングはこれに任せているのですが、これが中々思い通りに動いてくれない。

以前にも launchctl に触れたことはあって、その時はそんな手こずらなかった印象が残っているだけに、余計に焦りを募らせるわけです。

そんな作業の中で、debug とまではいかないですが*1
まず launchctl のステータスを捉えるのにこんなのが良かった、と言うヒントをメモしておこうと思います。
全てを忘れる未来の自分のために。 *2

Job failed to exec(3) for weird reason: 13 だったら、実行権限

launchctl で上手くいかない、と言う事例の多くは、この辺りが殆ど。

launchctl で呼び出している実行ファイルに実行権限がない場合、この Job failed to exec(3) for weird reason: 13 と言うログを吐いて動作してくれないようです。

ですのでこのエラー見たら、
ProgramArguments key に設定したファイルの*3の実行権限を確認すると良いかと。
そして権限が不十分だったら、chmod +x <file/to/path> とかで実行権限を与えてやる、となりますかね。

ちなみに。
ここでターゲットにしている agents は ~/Library/LaunchAgents で扱うようなもの ;

Note that per-user configuration files (LaunchAgents) must be owned by the user loading them. All system-wide daemons (LaunchDaemons) must be owned by root.
:
~/Library/LaunchAgents Per-user agents provided by the user.

なので、例えばここで述べられているような、;

Well, I finally worked through my problem and have found a solution!
:
I also had troubles with permissions and found that the "bin" folder I created and placed the script into wasn't owned by root. So I ran chown and chmod on my files and folders. Like this.

sudo chown root:wheel bin
sudo chown root:wheel adbind.bash
sudo chmod 755 adbind.bash
sudo chown root:wheel com.xxxx.adbind.plist
sudo chmod 755 com.xxxx.adbind.plist

sudo 経由するとか、chown でオーナーは気にする必要ない。...んじゃないかと思う。
この辺りで言われているように。;

When you run launchctl as a normal user (e.g. launchctl load), it interacts with your user instance of launchd to manage Launch Agents -- items that run in your user session, under your user identity.

When you run launchctl as root (e.g. sudo launchctl load), it interacts with the system instance of launchd to manage Launch Daemons -- items that run in system context, as root.

と、これでも動かない場合、
今度は ProgramArguments key で呼んでいる実行ファイルの内容自身を疑ってみることになる、と。

StandardOutPathStandardErrorPath を入れてみるのは良いかも

Very hard to say without knowing anything about what's in the script; see this previous answer for some troubleshooting options. – Gordon Davisson Apr 19 '13 at 14:39

まさにその通り。です。

と言う事で、見て見なよ、と言われる "this previous answer" のリンクに。;

Add entries to the launchd .plist to record the script's output, and see if that includes any error messages or other indications of what's going wrong:

<key>StandardOutPath</key>
<string>/tmp/turtle.out</string>
<key>StandardErrorPath</key>
<string>/tmp/turtle.err</string>

It may help to edit the script to add debugging output, so you can tell more about how it's working (/not working).

ちなみに、今回のケースでは、これが解決の糸口となりました。*4

この手の問題が原因となる場合は、ログに Exited with code: 1 というステータスを吐くようです。

この方法を知ったキッカケとなったサイトとして、この辺りも挙げておこうかと思います。;

» Debugging launchd - Ars Technica OpenForum
» Logging with launchd | Erik's Lab

launchctl start .. で結果確認

lauchctl コマンドは start サブコマンドに関する以下記述を目にして。;

start job_label
Start the specified job by label. The expected use of this subcommand is for debugging and testing so that one can manually kick-start an on-demand server.

なるほど、と。

それまでは、あわてて plist を開き、StartCalendarInterval で開始時刻を数分後に書き換えては、ターミナル行き plist の unload && load、処理が始まるのをジッと待ち、開始したら コンソール.app を開き、横に並べながらログを眺めステータス確認。そして再びジッと処理が終わるのを待って、を都度繰り返し、かなり面倒な思いをしていたりする。(恥

今度からは、
テストしたいと思った任意のタイミングで launchctl start .. を叩けばヨロシ、となるわけです。

別途、動作確認用の plist を用意している

ズボラ人間故www、
確認-修正、と言う結構にストレスフルな作業に出来るだけ集中したい、と予め動作確認用の plist を別途用意しておくことを思いつく(笑

こんな感じで。 ;

この plist を launchctl load ... で叩きながら確認する。
勿論、ProgramArguments key で kick するのは、任意で。

あ、結構長くなってしまいましたね。

はい、おしまい。
です。

*1:と言うか、launchctl の debug 方法知らないだけwww

*2:ちなみに、この話は、汎用的な話は指向していなくて、今回の作業状況あってのお話です。
今回は「ある shellscript を、定期的に起動させたい。」
なので、例えば上述の "shellscript を" が何らかのソフトウェアとかだったりしたら、もしかしたら、あまり役に立ない話になるかもしれません。

*3:"Progam" key の方はどうなのかは検証してません。

*4:つまり、shellscript のコード自身の問題だった、と言う事だったわけで orz