概要
コマンドをなんともなしにうちこんではいるけど、コマンドってどこのあるんだろうか。
PATHを通すってよく聞くけど、どういうことなんだろうか。
そんなことを思った初心者に向けて書いた記事です。
コマンドのコードを読むとかはしないです。
ちなみに各コマンドはMacとzshにて試してますが、Unix系なら似たようなものです。
結論
先に結論を言ってしまうと、PATHを通すとは、外部コマンドの場所をコマンドサーチパスに登録し、外部コマンドをパスで指定せずとも実行できるようにすることです。
詳細は下記に記します。
内部コマンドと外部コマンド
コマンドには以下のように、シェルに組み込まれている内部コマンド(ビルトインコマンド)と、特定のディレクトリ配下にファイルとして置かれている外部コマンドがあります。
lsコマンドはどこにある?
ためしに ls
コマンドの場所を which
コマンドで見てみましょう。
$ which ls
出力:
/bin/ls
どうやら /bin
直下にあるようです。
/bin の中には何がある?
では次に/bin
の中を見てみましょう。
$ ls /bin
出力:
[ chmod dash df expr ksh ln mv pwd sh sync unlink
bash cp date echo hostname launchctl ls pax rm sleep tcsh wait4path
cat csh dd ed kill link mkdir ps rmdir stty test zsh
よく使うコマンドと同じ名前のファイルがありますね。
外部コマンドの実体はファイルです
試しにls
コマンドの中身を見てみると、バイナリファイルであることがわかります。
$ od -h /bin/ls | more
出力:
0000000 facf feed 0007 0100 0003 0000 0002 0000
0000020 0013 0000 0710 0000 0085 0020 0000 0000
0000040 0019 0000 0048 0000 5f5f 4150 4547 455a
0000060 4f52 0000 0000 0000 0000 0000 0000 0000
(略)
外部コマンドを実行するには
内部コマンドは、コンピュータ起動時にメモリに読み込まれていますが、外部コマンドは、ディスクにファイルとして存在し(/bin
配下など)、毎回ディスクから読み込まれるようになっています。
つまり、外部コマンドを実行する際は、直接パスを指定して外部コマンドを実行できます。
例: 直接ファイルの置き場所を指定してlsコマンドを実行
$ /bin/ls
上記のようにすればコマンドを実行できますが、それでは面倒なので PATH
という環境変数が用意されています。
これは厳密には**コマンドサーチパス(コマンド検索パス)**と呼ばれるものです。
直接パスを指定しなくても、プログラムが勝手にコマンドサーチパスを見てコマンドを検索するため、以下のように ls
コマンドが実行できるわけです。
$ ls
PATHの中身は、外部コマンドを有するディレクトリ群
PATH
の中身をいったん見るために echo
コマンドで PATH
を見てみます。
$ echo $PATH
出力:
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
結果をみるといくつかのディレクトリが:
で区切られて出力されました。
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/Library/Apple/usr/bin
これらが外部コマンドの置き場所(パス)を示しています。
PATHが通っていないと
PATH
が通っていなかったり、存在しないコマンドを実行しようとすると以下のようになります。
例: zshの場合
zsh: command not found: hogehoge
該当のコマンドを既に入れたはずなのに、not found
などと言われる場合、
PATH
が通ってないことが多いです。
PATHを通すには
PATH
を通すためにやることは、環境変数PATH
に、使いたいコマンドが置いてあるディレクトリのパスを追記する必要があります。
例えば、/hogehoge/bin
配下にあるphp
コマンドを使いたい場合、
/hogehoge/bin
を環境変数PATH
に追加します。
試しにexport
コマンドを用いて追加してみます。
$ export PATH="/hogehoge/bin:$PATH"
echo
で追加されているかどうか確認。(追加されたコマンドをうってみてもOK)
$ echo $PATH
出力:
/hogehoge/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
上記のように、環境変数にはexport
コマンドを用いて追加できますが、いちいちexport
コマンドを使って追加するのは面倒なので、基本的に使用しているシェルの設定ファイルに追記します。
こうすることでシェルを起動する際に、自動的にPATH
が上書きされるようになります。
例: zshの場合
HOMEディレクトリ配下の.zshrc
ファイルにて export
を用いて追記します。
export PATH="/hogehoge/bin:$PATH"
最後 $PATH
と書いていますが、これは既存の環境変数PATH
を展開しています。つまり、以下と同じ意味です。
export PATH="/hogehoge/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
このときに、既存のものを完全に上書きしてしまうと、いろいろなコマンドが使えなくなってしまうので注意。
例えば、以下のようにしてしまうと、/bin 配下などのコマンドが読み込まれなくなります。
export PATH="/hogehoge/bin"
以上のように、環境変数PATH
を用いると、所定の外部コマンドを直接パスを指定せずに実行することができるようになります。
シェルの設定ファイルに関してわからない方は、自分の使っているシェルを調べて、書き方をググって見るとよいです。
PATHの優先順位
PATH
には優先順位があります。
例えば以下の場合だと、左の/hogehoge/bin
から順番に読み込まれるようになっています。
PATH=/hogehoge/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin
例えば、/hogehoge/bin
と、/use/local/bin
にそれぞれphp
というコマンドがあった場合、
$ php
と実行した場合に読み込まれるのは、/hogehoge/bin
のphp
コマンドになるということです。
このように、PATH
を指定する際は、優先順位にも気をつける必要があります。
各コマンドの置き場所( /bin や /usr/local/bin など)の違い
外部コマンドの置き場所は、FHS(Filesystem Hierarchy Standard)で**「こういうコマンドはこの場所に置きましょうね!」**という形で標準化されています。
これにより、どのLinux系のシステムをいじっても、「この/bin
ってディレクトリには緊急時でも使えるコアなコマンドが置いてあるんだな」と一目瞭然になるわけです。
(ただし、標準化されているとはいえ、強制しているわけではないので、各OSごとで変なコマンドが変な場所にあったりすることも)
これらで標準化されている外部コマンドの置き場所、それぞれの違いを以下の表にまとめてみましたが、一個ずつ見ていきます。
| ディレクトリ | シングルユーザモード | ひとこと概要 |
|----------------|----------------------|------------|----------------|
| /bin | 利用可 | 緊急時でも使えるやつ |
| /usr/bin | 利用不可 | 一般的なやつ |
| /usr/local/bin | 利用不可 | 自作のスクリプトとか |
| /sbin | 利用可 | スーパーユーザー(root)特権が必要 |
| /usr/sbin | 利用不可 | スーパーユーザー(root)特権が必要 |
/bin
シングルユーザモードでも使える一番コアな外部コマンドをこのディレクトリ配下に置きます。
シングルユーザモードとは、OSが正常に起動できないときなどの非常時に利用するものです。
最初でも確認したとおり、筆者のMacbookProの/bin
には以下のコマンドが入っていましたね。
[ chmod dash df expr ksh ln mv pwd sh sync unlink
bash cp date echo hostname launchctl ls pax rm sleep tcsh wait4path
cat csh dd ed kill link mkdir ps rmdir stty test zsh
これらのコマンドについて知らない人は、調べてもらえれば、どれもシンプルかつ重要なコマンドであることがわかります。
/usr/bin
シングルユーザモードで使わず、基本的にパッケージマネージャ(パッケージ管理システム)に管理されるコマンドを置きます。
パッケージマネージャは各OSごとにいろいろなものがありますが、ここでは触れません。
実際どんなコマンドがあるかは、自分のマシンのディレクトリを覗いて確認してみましょう。
/usr/local/bin
シングルユーザモードで使わず、パッケージマネージャに管理されないコマンドを置きます。
ちなみに、Macユーザーおなじみのパッケージマネージャであるhomebrewですが、
このディレクトリを使います。
なぜhomebrewがこの場所を使うかは、homebrewのページに書いてあります。
翻訳すると、以下のように言っています。
Appleはこのディレクトリを非システムユーティリティ用に割り当てています。つまり、デフォルトでは /usr/local にはファイルが存在しないので、既存のツールやシステムツールを台無しにする心配はありません。
/sbin や /usr/sbin
基本的に上記の各階層のディレクトリと同じ扱いですが、bin
とは違い、システム管理者がいじるような管理用のコマンドを置きます。
これらはスーパーユーザー(root)権限が必要になるため、一般ユーザーでは使用できません。
まとめ
結論は先にも書いたとおり、
PATHを通すとは、外部コマンドの場所をコマンドサーチパスに登録し、外部コマンドをパスで指定せずとも実行できるようにすること
ということでした。
PATHを通すついでに、内部コマンドと外部コマンドにも言及している記事があまり見当たらなかったので、今回書いてみました。