brew-file
Homebrewのパッケージリストを管理するツール。
Homebrew-fileと書いたりbrew-fileと書いたりこのブログの中でも統一されて無くて良くないですが、
管理してるレポジトリ名がhomebrew-file
で
コマンド名はbrew-file
、brew
のサブコマンドとしてbrew file
で呼び出される様なものです。
なのでその時々の気分で変わってしまってすいません。(多分、brew-fileとしておくのが良いのかな、と最近は。)
Homebrew自体にも現在はbundleというBrewfileファイルに書き出す機能がありますが、
brew-fileではBrewfile自体をGitHubのレポジトリで管理したり、
また、brew install
時などに自動でBrewfileをアップデートしたり、
普段brew-file
というコマンドを意識せずに自動で管理できる様なものを目指しています。
ほんとはbundleの機能に追加できれば良いんですが、あちらRubyでこちらPythonで 統一するのも面倒だし、その先新しいこと加えるときにRubyよりPythonのが(個人的に)やりやすいので 別途の形に。
ちなみに、以前、そこそこ使われてきたのでbrew-fileのformulaを 公式のレポジトリに入れてもらおうかと思ったこともあったんですが、 上記の様にbundleという似た(今はもう)公式のツールがあるので微妙かな、ということで 入れないことにしました。
まあ、Formulaの更新も自由に出来るので管理上は公式に入ってない方が楽なのでそれはそれで良いかな、と。
Linuxへの対応
今年はじめLinuxbrewがHomebrewに統一されたのでそれを機に Linuxでも本格的にHomebrewを使うためbrew-fileもLinux対応させました。
ただ、自分で使っていたのがRedHat系で、 最近WindowsでWindows Subsystem for Linux(WSL)なUbuntuの所でエラーが出て使えなかったので それに対応させました。
Debian系への対応
ここで問題になったRedHat系とDebian系の違いは、/bin/sh
の違いです。
RedHat系はBash、Debian系はDash。
brew-fileの中で、外部コマンドをsubprocess.Popen
で呼び出している部分がありますが、
brew
コマンドを呼ぶ際、brew-fileの設定でbrew-file
へのラッパー関数に設定している場合があるので、
その場合のループを防ぐためにcommand brew
の様な呼び方をしていました。
これでMacでもRedHat系でも問題なかったのですが、Ubuntuでやってみると
[ERROR]: Failed at command: command brew --prefix
というエラー。実際にはPopenが
command brew --prefix: [Errno 2] No such file or directory
みたいなエラーを出しています。
簡単なスクリプト例としては
1 2 3 |
|
とか。Ubuntuとかで実行すると
FileNotFoundError: [Errno 2] layouto such file or directory: 'command': 'command'
とか出ると思います。
これがDashではcommand
というものがないのだ、と思ってたんですが、
普通に
$ /bin/sh # Dash起動
$ command echo foo
foo
とかは出来ます。 ちょっとこの辺調べようとしたんですがよくわからないままなのでまたそのうち。。。
とりあえずcommand brew...
というのがうまく行かないので、
Bashで直接やれば、ということで
["bash", "-i", "-c", "brew ls"]
みたいなものを渡してみたんですが、これがRedHat系で
Package bash-completion was not found in the pkg-config search path.
Perhaps you should add the directory containing `bash-completion.pc'
to the PKG_CONFIG_PATH environment variable
No package 'bash-completion' found
bash: /yum: No such file or directory
というエラーを出しました。
どうやらbrewコマンドの中での何かしら環境変数の設定とかがうまくいってない模様。
Popen
呼ぶときには現在の環境変数全てを渡す様なことはしているので、ちょっとよくわからない。
PKG_CONFIG_PATH云々はわかりますが、そもそもなんでこういう事が出てくるか、 というのがbrewの中身を見たりしないとちょっと理解できなくて、 面倒なので見てません。
ただ、そもそも-i
を付けてインタラクティブモードでbash
を呼ぶ必要があるのか、というところで、
-i
ナシにしてみるとうまくいきました。
["bash", "-c", "brew ls"]
みたいな感じ。
ただ、これも最後の実際のコマンドの部分がまとめた状態になるので余り良くない。
ということで、関数、aliasを無視するにどうするか、と思ったところ、
単にbrew
へのフルパスを取ってやるのが一番楽だし正確かな、ということでそうしました。
ちょっと/bin/shに関する部分やsubprocessで呼ぶ際の環境、さらには subprocess.Popenでのshellやexecutable引数の意味、など もう一度ちゃんと理解しようと調べ始めて面倒になって中途半端な認識になってるので、 またそのうちまとめられれば、とは思ってます。
Ref:
How to use the bash shell with Python’s subprocess module instead of /bin/sh - SaltyCrane Blog