2013年1月29日火曜日

PATH環境変数内の、~/bin, /bin, /usr/bin, /usr/local/binなどの順番

ターミナルでシェルを使う場合の小ネタです。初心者には重要かもしれません。知っている人は今さらと思うかもしれませんが。
私は、以前はtcshを使っていました。Mac OS X 10.6.2までターミナルのデフォルトのシェルだったからです。Tiger (10.6.4)の時からbashにしました。乗り換えが1世代遅れたのは、使い方に若干慣れないところがあったのと、.tcshrcから.bashrc, .bash_profileへの変更が面倒だったためです。シェルスクリプトは/bin/shで書くことにしています。

今回の本題は、tcsh, bashのどちらにも関係するのですが、PATH環境変数内に設定するディレクトリの順番です。別の考え方もあると思いますので、参考ということで。

PATH環境変数は、コマンドを探すときのディレクトリの順番を指定するものです。PATH変数に含まれていないディレクトリにあるコマンドを指定しても、"コマンドが見つかりません"といったエラーがでます。

$ chdir
-bash: chdir コマンドが見つかりません

ディレクトリにコマンドが存在するのに上のようなエラーが出る時は、PATH環境変数にそのディレクトリが含まれていない(PATHが通っていないと言いますね)か、そのコマンドに実行権がないか、csh系だとrehashしていないという場合が多いです。(自分の経験では)

現在の私のPATH環境変数は、以下のようになっています。

$ echo $PATH
/Users/karuku/bin:/Users/karuku/local/bin:/usr/local/bin:/opt/local/bin:/usr/local/sbin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/clamXav/bin

基本的な考え方は、特殊なもの、局所的なものを先頭に持ってくる、標準的なものは後ろにするというふうにしています。一部、その考え方に沿っていないところもありますが。

定義順にそれぞれの使用目的を書いてみます。

/Users/karuku/bin - ホームディレクトリ下のbinです。自分で作成したスクリプト類を置いています
/Users/karuku/local/bin - テスト目的でインストールしたいものを置いています
/usr/local/bin - MacPortsでサポートされていないコマンドを置いています
/opt/local/bin - MacPortsでサポートされているコマンドを置いています
/usr/local/sbin - MacPortsでサポートされていないシステムコマンドを置いています
/opt/local/sbin - MacPortsでサポートされているシステムコマンドを置いています
/usr/bin - 一般的なユーティリティ、プログラミングツール、アプリケーション
/bin - ユーザ用ユーティリティの基本的なもの。シングルユーザ環境、マルチユーザ環境どちらでも使用する
/usr/sbin - (ユーザによって実行される) システムデーモン、およびシステムユーティリティ
/sbin - (ユーザによって実行される) システムデーモン、およびシステムユーティリティ
/opt/X11/bin - XquartzでインストールされるX Window System
/usr/local/clamXav/bin - ウィルスチェッカー clamav / clamXavをインストールしています。

( /binや/usr/binなどのシステムディレクトリ説明にはjman hierの記述を使いました。)

最後のふたつの /opt/X11/binと/usr/local/clamXav/binは、最初の考え方の原則に反していますね。

/opt/X11/bin (X11)は、Xquartsをインストールした際に、/etc/paths.dに登録されました。ここに登録されると、ログイン時に/etc/profile内で、その時のPATH変数にアペンドされる形になるようです。
X11は、以前Mac OS Xに使いたいGUIアプリケーションが少なかったころや、会社でLinuxマシンを使う際に使っていましたが、最近は全く使っていません。LinuxかFreeBSDを使うこともなさそうなので、当面このままにするつもりです。

clamXavは、ターミナルからではなく、Finderから使う場合がほとんどなので、PATHから外してもいいかもしれないですね。

コマンド名がぶつかる場合

たまに、同名のコマンドがそれぞれのディレクトリにある場合があります。上の考え方の場合、通常は使いたいコマンドが先に来ているので問題ないのですが、たまに後のディレクトリのコマンドをデフォルトとして使いたい場合があります。
例えば、rsyncはAppleの提供しているバージョンとMacPortsでインストールされるバージョンでは、HFS+関係の属性等を扱うオプションが違います。MacPortsのrsyncを使おうと思った訳ではなく、依存関係でインストールされたのですが。

こういう場合は以下のようにしています。

シェルスクリプトの場合は、以下のようにフルパスで記述します。

RSYNC=/usr/bin/rsync
RSYNC -hfsv ...

コマンドラインから使う場合は、~/bin から使いたいバージョンのコマンドにシンボリックリンクを張ります。~/binは先頭にあるので、意識せずに使いたいバージョンのコマンドが使えます。

$ ln -s /usr/bin/rsync ~/bin

別の解決方法として、alias が考えられますがあまり使っていません。特に意識していませんでしたが、bashの場合、whichコマンドでaliasで定義したコマンドが表示されないから(方法を知らないだけかもしれませんが)というような理由です。
また、bashに移行した初めの頃は、tcshも併用していたので、~/binの一箇所に設定しておけばいいからという理由もあったかもしれません。(ちょっとうろ覚えです)

0 件のコメント:

コメントを投稿