プログラミング初心者がぶち当たりやすい壁のひとつ、「パスを通す」 という謎の儀式。
学習を始めた頃は、
ネットに載っている .zshrc の設定をそのままコピペ
→ コマンド動いた!すご!!
という感じで特に気にせず。魔法みたいなもんです。
ところが、開発を続けるうちに話が変わってきました。
複数のバージョン管理ツールをインストールした結果、
which node したら... コレジャナイ!!
使いたいものとは違うnodeが使われているみたいです。
この記事では、パス脳死コピペ地獄から脱却するべく、
パスとは?コマンドとは?ターミナルとは?について理解してみようと思います!
1. そもそもコマンドってなに?
私は魔法だと思っていました!
謎の文字列を打つと何かしらの処理が実行される魔法...。
でもめちゃくちゃ大事なのが、コマンドはただのファイルだという衝撃の事実。
一旦見てみましょう。
% ls -la /bin
total 9560
drwxr-xr-x@ 39 root wheel 1248 10月 29 10:21 .
drwxr-xr-x 22 root wheel 704 10月 29 10:21 ..
-rwxr-xr-x 2 root wheel 101472 10月 29 10:21 [
-r-xr-xr-x 1 root wheel 1310208 10月 29 10:21 bash
-rwxr-xr-x 1 root wheel 118992 10月 29 10:21 cat
-rwxr-xr-x 1 root wheel 120656 10月 29 10:21 chmod
-rwxr-xr-x 1 root wheel 153360 10月 29 10:21 cp
-rwxr-xr-x 2 root wheel 1091936 10月 29 10:21 csh
-rwxr-xr-x 1 root wheel 274272 10月 29 10:21 dash
-rwxr-xr-x 1 root wheel 135392 10月 29 10:21 date
-rwxr-xr-x 1 root wheel 152576 10月 29 10:21 dd
-rwxr-xr-x 1 root wheel 119152 10月 29 10:21 df
-rwxr-xr-x 1 root wheel 101136 10月 29 10:21 echo
-rwxr-xr-x 1 root wheel 202528 10月 29 10:21 ed
-rwxr-xr-x 1 root wheel 102000 10月 29 10:21 expr
-rwxr-xr-x 1 root wheel 101184 10月 29 10:21 hostname
-rwxr-xr-x 1 root wheel 101504 10月 29 10:21 kill
-r-xr-xr-x 1 root wheel 2549488 10月 29 10:21 ksh
-rwxr-xr-x 1 root wheel 364320 10月 29 10:21 launchctl
-rwxr-xr-x 2 root wheel 102192 10月 29 10:21 link
-rwxr-xr-x 2 root wheel 102192 10月 29 10:21 ln
-rwxr-xr-x 1 root wheel 154624 10月 29 10:21 ls
-rwxr-xr-x 1 root wheel 101472 10月 29 10:21 mkdir
-rwxr-xr-x 1 root wheel 119440 10月 29 10:21 mv
-rwxr-xr-x 1 root wheel 304672 10月 29 10:21 pax
-rwsr-xr-x 1 root wheel 170816 10月 29 10:21 ps
-rwxr-xr-x 1 root wheel 101296 10月 29 10:21 pwd
-rwxr-xr-x 1 root wheel 101072 10月 29 10:21 realpath
-rwxr-xr-x 2 root wheel 119216 10月 29 10:21 rm
-rwxr-xr-x 1 root wheel 101120 10月 29 10:21 rmdir
-rwxr-xr-x 1 root wheel 101232 10月 29 10:21 sh
-rwxr-xr-x 1 root wheel 101168 10月 29 10:21 sleep
-rwxr-xr-x 1 root wheel 135504 10月 29 10:21 stty
-rwxr-xr-x 1 root wheel 100784 10月 29 10:21 sync
-rwxr-xr-x 2 root wheel 1091936 10月 29 10:21 tcsh
-rwxr-xr-x 2 root wheel 101472 10月 29 10:21 test
-rwxr-xr-x 2 root wheel 119216 10月 29 10:21 unlink
-rwxr-xr-x 1 root wheel 101056 10月 29 10:21 wait4path
-rwxr-xr-x 1 root wheel 1361200 10月 29 10:21 zsh
/bin は、ログインユーザに関係なくOSにデフォルトで入っているコマンドたちの居場所です。
cat とか ls とか kill とか、よく見る重要そうなコマンドたちのファイルがありますね。
このファイルの中身を見てみると、該当コマンドが叩かれた時の処理と思われる難しそうな文字列が並んでいます。
普段脳死で叩いているコマンドたちは、実はファイルです!!(衝撃)
2. 「パスを通す」となんの関係があるの?
コマンドはそれぞれ実行ファイルを持っているという事実が分かったら、あとはとっても簡単です。
「パスを通す」というのは、ここにコマンドを見に行ってね という設定をしているのです!
コマンドには実行ファイルがあるけど、それだけではシェル(コマンドを解釈するひとです!後述)はどこにファイルがあるのか分からない。
それをシェルに教えてあげるのがパス。みたいな感じです。
実際のパスを見てみましょう。
%echo $PATH
/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin
これ、コマンドを探しに行ってほしいディレクトリをコロンつなぎで書いているだけなんです!
/opt/homebrew/bin
/usr/local/bin
/usr/bin
/bin
何かしらのコマンドが叩かれたら、シェルはこのパスをみて、先頭のディレクトリから順番にコマンドないかな〜って探しにいきます。
新しいツールを入れた際にパスを通す必要があるのは、
この場所に新しいコマンドたちを入れたよ!
これからはここも探しに行ってね!
というメッセージをシェルに伝えるためだったのです(優しい)
3. nodeコレジャナイ問題はなんだったのか
意図したものとは違うnodeが使われている問題。
node というコマンドを叩くと、シェルはパスに書かれているディレクトリを先頭から順番に調べて、最初に見つかった node を実行します。
なので、複数のバージョン管理ツールを入れると問題が起こる...
- asdf が管理する node
- Homebrew が管理する node
- OS が標準で持っている node
これらのどれが優先されるかはパスの並び順次第です。
使いたいnodeよりも優先されるnodeが存在したため、意図したものとは違うnodeが使われていたみたいです。
複数のバージョン管理ツールがある場合には、使いたいものが入っているディレクトリをパスの先頭に置く必要があります。
(併用しないのがいちばんです...!)
4. シェルってなに?
さっき出てきたシェル。
シェルとは、コマンドを解釈する存在です。
zsh、bash などがよく使われますね。
コマンドが叩かれたら、シェルはパスを見て、どの実行ファイルを呼び出すかを決定します。
実際に処理を実行するのはカーネルの役割です。
ちなみにターミナルは、ただの「文字を入力したら結果が出るアプリ」です。
- カーネルに実行してほしい処理を人間が簡単に伝えられる
- カーネルが実行した処理の結果を人間が理解できる形で返す
入力 / 出力を担う仲介役的な存在です!
コマンドを叩いた時の流れはこんな感じ↓
人間がターミナルでコマンドを叩く
↓
シェルがパスを見に行ってどのファイルを実行するかを決める
↓
カーネルが処理を実行する
↓
ターミナルに結果を出力する
5. おわりに
魔法だと思っていたコマンドには実行ファイルが存在し、そのファイルの場所をシェルに教えるのがパスの役割。
「パスを通す」という行為の意味と、コマンド実行時の流れがなんとなく理解できたような気がします!!
ひとつずつ脳死コピペを減らしていくことで、エンジニアとして少しずつレベルアップしていきたいですね...!