« 検索条件に一致するファイルを他所にコピーしてからシンボリックリンクに置き換えるシェルスクリプト | ホーム

2014年10月22日

Yosemiteアップデートでlaunchdが死亡した

Yosemiteアップデートでlaunchdが死亡した

MacをYosemiteにアップデートしたら自前のlaunchdジョブが軒並実行されなくなって死亡したので対応した。

結論

  • launchdから直接叩くコマンド: /usr/local/bin にパスが通らないのでフルパスで実行する。
  • launchdからシェルスクリプトを呼び出して叩くコマンド: 事前に launchctl setenv PATH /usr/local/bin:$PATH とかしておけばOK。

ジョブの作成・登録

記事中では便宜的にターミナル使っているけど実際のジョブ作成にはLingon 3を使っています。

経緯

Yosemiteでは /etc/launchd.conf が無効にされた上に /usr/local/bin が有効にならないバグがあるらしい。

手元で検証したところ、手動でパスを通しても /usr/local/bin 以下のコマンドが呼べない。

$ launchctl setenv PATH /usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
$ cat ~/Library/LaunchAgents/org.retlet.polipo.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>org.retlet.polipo</string>
    <key>ProgramArguments</key>
    <array>
        <string>polipo</string>
        <string>-c</string>
        <string>~/Dropbox/settings/polipo/config</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

$ launchctl start org.retlet.polipo

これだとダメでpolipoの呼び出しをフルパスに変えると動いた。

$ vim ~/Library/LaunchAgents/org.retlet.polipo.plist

...
        <string>/usr/local/bin/polipo</string>

$ launchctl unload ~/Library/LaunchAgents/org.retlet.polipo.plist
$ launchctl load ~/Library/LaunchAgents/org.retlet.polipo.plist

ただし、launchdジョブからシェルスクリプトを呼び出してそこから別のコマンドを叩く場合だとPATH指定が有効だった。

試しに以下のようなシェルスクリプトをジョブ経由で実行してみると、事前にPATH指定をしていれば各コマンドのフルパスが返ってくる。

$ vim ~/launchd-test.sh

#!/bin/sh

LOG="/Users/retlet/launchd-test.txt"
launchctl getenv PATH >>${LOG}
which python >>${LOG}
which polipo >>${LOG}
which gfind >>${LOG}
which ffmpeg >>${LOG}

/usr/local/bin にパスが通っていない場合。

$ launchctl unsetenv PATH
$ launchctl start org.retlet.launchd-test
$ cat ~/launchd-test.txt
/usr/bin/python

/usr/local/bin にパスが通っている場合。

$ launchctl setenv PATH /usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
$ launchctl start org.retlet.launchd-test
$ cat ~/launchd-test.txt
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
/usr/local/bin/python
/usr/local/bin/polipo
/usr/local/bin/gfind
/usr/local/bin/ffmpeg

定期実行しているいくつかのジョブではシェルスクリプトからコマンドを呼んでいるので、ログイン時にsetenvだけするジョブを別途用意することにした。

$ vim ~/Library/LaunchAgents/org.retlet.setenv.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>org.retlet.setenv</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/retlet/Dropbox/settings/script/setenv/setenv.sh</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

$ vim ~/Dropbox/settings/script/setenv/setenv.sh

#!/bin/sh
launchctl setenv PATH /usr/local/bin:$PATH

$ chmod u+x ~/Dropbox/settings/script/setenv/setenv.sh
$ launchctl load ~/Library/LaunchAgents/org.retlet.setenv.plist

こんな感じにしとけばたぶん今まで通り機能する。

トラックバック(0)

トラックバックURL: http://retlet.net/cgi-bin/mt5/mt-tb.cgi/96