今日は仕事でDockerfileを編集して、新しいライブラリをインストールする業務をしていました。
主に、composerをインストールして、composerでライブラリを新規に追加し使用できるようにしていました。
composerをインストールした後、composer install コマンドを実行したところ以下のコメントが表示されました。
・・・
RUN composer install --no-dev
0.257 /usr/bin/env: php: No such file or directory
ERROR: executor failed running [/bin/sh -c composer install --no-dev]: exit code: 127
・・・
2行目の/usr/bin/env: php: No such file or directory
を見るとphp
のパスが上手く通っていないことがわかります。
Dockerfileの前半でphpをインストールしたのち、上記のcomposer install
コマンドが実行されるのですが、先にインストールされたphpのパスが設定されていないためにcomposerがphpを見つけられずエラーが出ている状態でした。
そこで、下記のとおりcomposer installコマンドの前に、phpのパスを通す(設定)ことで、composerがphpを見つけることができて、エラーを解決することができました。
・・・
ENV PATH $PATH:/usr/bin
RUN composer install --no-dev
・・・
ここで、「パスを通す」というのが、なにをやっていることなのか整理したいと思います。
※ 上記はDockerfileのパスを通すときの書き方ですが、ターミナル上でコマンドを叩いてパスを通す方法も記事内で説明しています。
「パスを通す」とは?
結論から言うと、「パスを通す」とは、環境変数$PATHにプログラムのパス(どこにあるか)を設定することです。
言い換えると、「パスを通す」とは、実行ファイルの居場所をコマンドの実行者(OS)に教えてあげることです。
順番に説明していきます。
lsコマンドがどこからでも実行できる理由
たとえば、ls
コマンドについて考えます。(windowsの方はpower shellで実行するコマンドで置き換えて考えください)
ls
コマンドは基本的にどこでも実行できると思います。(なぜなら、最初からパスが通っているプログラムだから)
$ ls
Applications Downloads Movies Postman package-lock.json
Desktop Google Drive Music Public
Documents Library Pictures Puppeteer
$ cd Puppeteer
$ ls
test url_list
上記を見ると、home
ディレクトリでも、Puppeteer
ディレクトリでも、ls
コマンドが実行できています。
これは、ls
コマンドで実行されているプログラム(実行可能ファイル)の「パスが通っている」ためです。
つまり、ls
コマンドで実行されるプログラム(実行可能ファイル)が置かれている場所を設定しているため、どこからでも実行することができるのです。
つまりつまり、ls
コマンドで実行されるプログラム(実行可能ファイル)が置かれている場所をOSに教えてあげているため、どこからでも実行することができるのです。
lsコマンドのパス(PATH)を確認してみる
まずは、whereisコマンドで、lsコマンドに関わるプログラム(実行可能ファイル = バイナリファイル、以下プログラム)がどこにあるか確認します。
# 以下のコマンドに$は入力しないこと
$ whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1
コマンドの結果をみると、ls
コマンドのプログラムls
が/bin
の下にあることが分かります。(「どこにあるか」というのを「パス」と言います。)
「whereisコマンド」:指定したコマンドに関連するファイルのパスを表示する
次に、上記のパス(PATH)を、コマンドの実行者(OS)が知っているのかを確認してみます。
環境変数$PATHとは?
結論から言うと、OSは環境変数$PATHにプログラムの場所を記録しています。
つまり、パスを通したプログラムは全てこの環境変数$PATHの中に記録されています。
ちなみに「環境変数」とはOSが設定値などを永続的に保存しておくための変数(数値や文字列などを入れておく箱)です。
「環境変数」:OSが設定値などを永続的に保存しておくための箱
それでは環境変数$PATHの中身を確認してみましょう。
以下のように、echoコマンドを使用して、変数の値を表示します。
# 以下のコマンドに$は入力しないこと
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
環境変数は、複数の値を持つ場合はコロン(:)で区切られています。(Windowsではセミコロン;)
つまり、上記の場合、環境変数$PATHの中身は次の5つです。
$ echo $PATH
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
これを見てお気付きかもしれませんが、上記からls
が見当たりません。。。
実は、「パスを通す」というのは「プログラムが置かれている場所を教えること」なので、上記のように「このディレクトリにあるかもよ」という感じで登録されています。
例えば、ls
コマンドを実行すると、コマンド実行者のOSは、上記の候補となる場所の中からlsというプログラムを探して、見つけたら実行していきます。
優先順位として、探す順番が決まっていて、左から順に探していくことになります。優先順位は左から順です。(縦に並び替えたやつで言うと、優先順位は上から順です。)
「環境変数の優先順位」:左から順(一番左が一番優先される)
ここで、再度以下の結果を思い出してみましょう。
# 以下のコマンドに$は入力しないこと
$ whereis ls
ls: /bin/ls /usr/share/man/man1/ls.1
ls
コマンドのプログラムls
は、/bin
の下にありました。
そして、OSがプログラムを探す場所は次のとおりです。
# 以下のコマンドに$は入力しないこと
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
左から3つ目に/bin
があります。
これによって、コマンドの実行者(OS)はどこからls
コマンドを叩かれても、プログラムls
を見つけ出しls
コマンドを実行することができるのです。
パスを通す方法は?
それでは、lsコマンドのように「パスを通す」ためには、lsコマンドのように「OSにプログラムが置かれている場所を教える」ためには、どうすればいいのでしょうか?
それは簡単で、これまでの話のとおり、次の手順を踏めばOKです。
- プログラムが置かれている場所を確認する。
- 環境変数$PATHに探す場所を設定する。(これを「パスを通す」と言う)
1. プログラムの場所を確認
これは、where
コマンド、whereis
コマンド、find
コマンドなど調べ方はたくさんあると思います。
※ 自作のプログラム(実行可能ファイル)であれば、調べるまでもなくどこにあるか、またはどこにでも自由に配置できると思うのでここは割愛して大丈夫です。
ここでは、whereis
コマンドで調べる方法を紹介します。
今回はgit
コマンドで実行されるプログラムgit
がどこにあるか確認したいと思います。(git をインストールしていない人はpwdとかhistoryとかで試してみてください)
# 以下のコマンドに$は入力しないこと
$ whereis git
git: /usr/bin/git /Library/Developer/CommandLineTools/usr/share/man/man1/git.1
$ whereis pwd
pwd: /bin/pwd /usr/share/man/man1/pwd.1
$ whereis history
history: /usr/share/man/man1/builtin.1
上記より、それぞれのプログラムがどこに置かれているかが分かります。メモしておきましょう。
(※ すみません。上記のように有名どころはすでにパスが通っていると思います)
2. 環境変数$PATHにパスを設定する(パスを通す)
ターミナル上で環境変数$PATHを設定するときは、次のようにします。
たとえば、上記のgit
のパス/usr/bin
を設定する場合(ほとんどの人が既に登録されていると思うが。。。)
# 以下のコマンドに$は入力しないこと
$ export PATH=$PATH:/usr/bin
# 以下のコマンドで$PATHの中身を確認する
$ echo $PATH
exportコマンドは環境変数を設定するコマンドである。
上記の例のように、PATH=$PATH:/usr/bin
とすることで、もともと環境変数$PATHに書いてあった内容を消すことなく、$PATH
の内容の末尾に:/usr/bin
を追記することができる。
注意する点としては、パスはプログラム名までは登録しないこと。
あくまでもOSがプログラムを探す場所を環境変数$PATHに登録するので、
今回の例であれば$ export PATH=$PATH:/usr/bin/git
ではなく$ export PATH=$PATH:/usr/bin
とする。
いちいち環境変数にプログラム名まで設定すると管理しづらくなるため注意すること。
パスを通したけどエラーが出るとき
パスを通しても、プログラムが実行されなかったり、パスが通ってないよってエラーが出る場合は以下を確認してみましょう。
- パスあっている?
- パーミッションは大丈夫?(実行権限ある?)
- それはプログラム?実行可能ファイル?(もしかしたらディレクトリかも)
最後に、「LPICの勉強しよう」
今回は「パスを通す」という基本事項について触れてきましたが、業務ではdockerfileを扱っていてのでこの基本事項ですらかなり苦戦しました。
そこで思い出したのは「LPIC」についてです。
私自身、基本情報技術者試験に出題されるような内容はある程度、理解できていると思っていますが、LPICに出題されるようなLinuxファイルシステム構造については理解が足りていないように感じます。
上司にも勧められていたので資格取得駆動で勉強していきたいなと改めて思いました。