問題発生の背景
macOSアプリがあり、昔からpkgbuild
やproductbuild
を使ってpkgインストーラーを作っています。
そのインストーラーは作成する際にpostinstallスクリプトの設定をしており、長い間、動いていました。中身は
#!/bin/sh
; postinstall.sh
; Script path
; echo Script path: "$0"
; Package path
; echo $1
; Target location
; echo $2
; Target volume
; echo $3
SHORTCUT_NAME="hogefuga"
; ショートカットが既に存在しているとエラーになってインストール失敗するので消す
if [ -r ~/Desktop/"$SHORTCUT_NAME" ]; then
rm ~/Desktop/"$SHORTCUT_NAME"
fi
ln -s $2 ~/Desktop/"$SHORTCUT_NAME"
こんな感じの、アプリをインストールした後に、.app
ファイルへのショートカットをデスクトップ画面に出すという、Windows文化圏のアレです。macOS文化圏だとあんま主流じゃないと思うんですけど、Windowsと揃えておきたいということでこういう仕様になっています。
ちなみにpkgインストーラー作り慣れてる方だと、「は?postinstallの$2
って(インストール先変更しない限り)普通/Applications
でしょ。ディレクトリへのリンク張ってどうすんだ」と思われるかもしれませんが、実は条件次第で.appのショートカットが張れます。
問題発生
ある日、新しくインストーラーを作ったら、インストールした.app
へのシンボリックリンクではなく、Applications
ディレクトリへのシンボリックリンクが張られるようになってしまいました。
結論
呼び出すスクリプトファイル名の拡張子(.sh)の有無で挙動が変わります。
拡張子ありの場合
postinstallは普通に1回実行され、$2には.appファイルのパスが入る。
前述した条件であり、これまで長いこと利用してきたパターンになります。
拡張子なしの場合
何故かpostinstallが2回実行される。 しかも1回目は$2に.appファイルのパスが入るものの、2回目は/Applicationsが渡されるため、上述のスクリプトだと1回目で作成したショートカットが消され、2回目で作られた/Applications
のショートカットが残る形になります。
感想
という訳で、「『CLIから実行するShellファイルには拡張子つけない』という慣習を長年無視してたけど、最近気になり拡張子を取っちゃった」らこの仕様を踏んづけたという次第でございます。自分はフロントよりのWebアプリ屋兼クロスプラットフォームアプリ屋なのでOS周りとか低レイヤーの知識が無いせいもあるんですが、本気で意味が分からん……。
いやーそれにしても条件を探すのにかなり手こずりました。あの見づらい/var/log/install.log
とずっとにらめっこして、仕様について気付くの結構時間かかりましたし。OSのバグの線からパーミッションやら思いつく限り調べても原因というかこの現象の仕組みは分からなかったのですが、途中一つ気になることがあったので書いときます。
拡張子有り無しでpkgbuild
コマンド打って出力ログを比較していたんですが、一行気になる文が差分として出てきたんですよ。
//ファイル名に拡張子無し(問題発生時)
pkgbuild: Adding top-level postinstall script
これ見る限り、どうやら内部的にtop-levelとして判定されているか否かがこの挙動の違いを生んでいるようです。