🔗

Linux学習:基礎編|パスを通すとは何ぞや!環境変数PATHとは?エンジニアなら避けては通れぬ...

    Linux学習記録|なんとなく理解禁止シリーズ

「パスを通す」とは何ぞや

「パスを通す」とは特定のプログラムを「プログラムの名前だけで実行できるように道を示すこと」です。

...どういうことじゃい?ということで、お馴染みの「git」というコマンドを例にその意味を解釈してみます。

learning-linux-basic-path-001@1.5x.jpg

「gitにパスが通っている」とは、「git」という名前を打てば/usr/bin/ディレクトリにあるgitファイルを実行できるように道が示されているという意味になります。図解にもしましたが、パスの通ったコマンドの処理の流れは下記のようなイメージです。

  • git statusとCLIで打たれる
  • gitという実行ファイルのあるパスをPATHという環境変数を頼りに探す
  • /usr/bin/というパスの中にgitという実行ファイルが見つかる
  • gitファイルを解析してgit statusという指示を実行する

ちなみに/usr/bin/git statusとCLIに打ってもgit statusと全く同じ実行ができます。つまり、パスを通せば、「本来なら/usr/bin/git statusとフルパスで実行ファイルを打たないといけないところ、git statusと楽に実行ができる」ということになります。

念の為、Linuxの資格でもお馴染みの「Linuc」の言葉の引用も参照しておきます。

シェルが探しに行くディレクトリを設定する作業を、「パスを通す」と言います。正確には「コマンドサーチパス」、すなわちコマンドを探しにいくパスの設定をする、ということですね。
Linux豆知識 019 パスを通す|Linuc

つまるところパスを通すとは「プログラムの実行ファイルを探しやすいように道を示してあげる」という言い方ができるかと思います。

環境変数PATHとは何だい

では、PATHとは何か。PATHとはコマンド探索のためのパス格納庫のようなものです。CLIで簡単にその実態は確認できます。

$ printenv PATH
# /user/.nodenv/shims:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/homebrew/bin:~/.docker/bin

printenvとは、引数に環境変数を設定することでその環境変数を表示できるコマンドです。(LinuCレベル1 101試験の例題と解説 1.03.1 コマンドラインの操作

もちろん実行結果は人によって異なりますが...ちょっと1行で返されて見づらいので、パス毎に改行してみます。

/Users/***/.nodenv/shims:
/usr/local/bin:
/System/Cryptexes/App/usr/bin:
/usr/bin:
/bin:
/usr/sbin:
/sbin:
/opt/homebrew/bin:
~/.docker/bin

なるほど、:で複数のパスを区切っていたわけですね。そして、このPATHをコマンド探索時にどのように活用しているか。再びgitを例にして見てみます。

  • /Users/***/.nodenv/shims:gitあるか? -> No.
  • /usr/local/bin/:gitあるか? -> Yes!
  • /usr/bin/gitを実行

このように、(Linuxでは)PATHの先頭から順番にgitという実行ファイルがあるかどうか探索していって、見つかった段階でそのパスの中にあるgitファイルを実行しています。

PATHの優先度について|Linux豆知識 019 パスを通す|Linuc

ちなみに、which gitと打てば環境変数PATHに基づいてそのコマンドの絶対パスを返してくれますよ。

$ which git
# /usr/bin/git

パスを通す方法

少しずつ実態が見えてきたところで、パスの通し方の解説です。結局パスを通すというのは、環境変数PATHを上書きしているだけです。実例を見てみましょう。

$ export PATH="/opt/hello/bin/:$PATH"

exportは環境変数をセットするコマンドで、$PATHはもちろん環境変数PATH自身を参照します。つまり、/opt/hello/bin/:(と元々のPATH)という文字列をPATHに再代入しているだけということ。

まとめると、環境変数PATHとはコマンド探索をする時に活用するパスの格納庫であり、そのPATHexportで更新すれば新たなパスを通すことができる。という訳です。

環境変数とは?変数との違いは?

この記事は「なんとなく理解」の禁止条例を出している(?)ので、環境変数もちゃんと理解していきます。

変数とはシェル上からだけ参照できる値のことで、環境変数とはシェルだけではなくシェルから起動された他のプログラムからも参照できる値となります。

...ん〜分かりづらいですね!CLIで実際に試してみます。

$ test="変数っす"
# `変数名=値`と直接入力すればOK
$ export TEST="環境変数でございます"
# 環境変数は`export`コマンドで挿入可能

$ echo $test
# 変数っす
$ echo $TEST
# 環境変数でございます

まずはこれが変数と環境変数の設定方法です。ちなみには「変数を取り出す」という役割があります。仮にecho testと叩いてもtestと返すだけなのでご注意を。

肝心の参照できる範囲ですが、例えば、helloという実行ファイルに下記が書かれていたとします。

#!/bin/bash
echo "hello $TEST"

このhelloというファイルを実行すると、hello 環境変数でございますと返すことができます。でも下記だと実行してもhelloとしか返してくれず変数は参照できません。

#!/bin/bash
echo "hello $test"

つまり、環境変数ならプログラムの中からも参照できるけど、変数だとシェル上からしか参照できないという事です。

【実践!】自分で実行ファイルを作ってパスを通してみる

ここまでの説明で以下のことが分かりました。

  • 「パスを通す」とは何か
  • 環境変数PATHの真相と設定方法
  • ついでにprintenvwhichコマンドの使い方

百聞は一見に如かずということで、簡単な実行ファイルを自作してパスを通して見ましょう!(作ってワクワク)

要件

## 概要
`hello [引数]`と打てば`Hey [引数] !`と返してくれる`hello`コマンド
例)
$ hello world
# Hey world!

## 詳細
* `~/Documents/path-learning/usr/local/bin`ディレクリの中に実行ファイルを配置
* フルパスじゃなく`hello`コマンドを打つだけで実行できるようにパスを通す
* シェルは`bash`を使う

ザックリと要件はこんなところです。僕も実際に試しましたが、全然簡単でした♪
さぁやって見ましょう!

ステップ1/3:実行ファイルを作成

せっかくなのでFinder等のGUIは使わずにCLIの真っ黒の画面だけでやってみます!

$ mkdir -p ~/Documents/path-learning/usr/local/bin
# ディレクトリの作成。`-p`で中間ディレクトリが無い場合も同時に作成可能
$ cd ~/Documents/path-learning/usr/local/bin
# 移動
$ vim hello
# `hello`というファイル作成

次にhello実行ファイルの中身を作成。

#!/bin/bash
echo "Hey $1!"
# vimエディタを使う場合、キーボードで`i`を打てば入力モードになります。入力ができたら`esc`を押してから`:wq`と入力すれば保存して閉じることが可能。
# `echo`は文字列の出力
# `$1`は第1引数の取り出し(`hello World`の場合は`World`=`$1`となる

保存して閉じたら、この実行ファイルが使えるかどうか、一度下記のコマンドを打って見ましょう!

$ ~/Documents/path-learning/usr/local/bin/hello World
# zsh: permission denied: /Users/***/Documents/path-learning/usr/local/bin/hello

何やらパーミッションエラーが出ました。/Users/***/Documents/path-learning/usr/local/bin/helloこのファイルには実行可能な権限が付与されていませんよ。と言われています。helloを実行ファイルとして扱うためには、権限の付与が必要になります。

ステップ2/3:実行権限(execute permission)を付与

chmod(change modeの略)というコマンドを使えばファイルやディレクトリにアクセス権限を付与できます。実行権限(execute permission)を付与するには+xというオプションをつけます。ちなみに権限削除は-x

$ chmod +x ~/Documents/path-learning/usr/local/bin/hello

これで一度helloの実行ファイルを呼び出して見ましょう!

$ ~/Documents/path-learning/usr/local/bin/hello World
# Hey World!

作ったシェルスクリプト通りに文字列が出力がされました!...と言っても毎回~/Documents/path-learning/usr/local/bin/helloこんな長いパスを打つのは面倒ですね。試しにhello Worldと打って見ましょう。

$ hello World
# zsh: command not found: hello

環境変数PATHについての理解があれば、なぜnot foundかお分かりかと!では本題のパスを通して見ましょう...!

ステップ3/3:パスを通す

$ export PATH="$HOME/Documents/path-learning/usr/local/bin/:$PATH"

この1行に本題の全てが詰まっています。順に説明していきますね。

つまり下記の操作をしています。

$ export PATH="$HOME/Documents/path-learning/usr/local/bin/:$PATH"
# `PATH`に、`~/Documents/path-learning/usr/local/bin/:(の後ろに元々のPATH)`という文字列を環境変数として再代入

これでパスを通せたので、試して見ましょう!

$ hello World
# Hey World!

無事にhelloコマンドだけで実行できました!

【応用】要件の追加

ここからは実務でありそうな応用編です。先輩から下記のような指示があったとします。

~/Documents/path-learning/usr/local/bin/jp/の中にやぁ $1!と日本語で返す実行ファイルも追加したので、今後はそっちにパスを通し直してください〜。

「パスを通し直す」「パスの向きを変える」...おぉ、なんだかこの言葉の意味が今まで以上に鮮明に理解できるではありませんか!!

テンションもぶち上がったところで、実務っぽく現在のパスの向きを確認しつつ進めていきましょう。

$ which hello
# /Users/***/Documents/path-learning/usr/local/bin//hello
$ export PATH="$HOME/Documents/path-learning/usr/local/bin/jp/:$PATH"
$ hello 世界
# やぁ 世界!

初めに現在のパスの向きをwhichコマンドで確かめて、次にexportで環境変数PATHの先頭に新たなパスを追加しています。これで.../jp/helloの実行ファイルにパスの向きを変えることができました!

余談(なんとなく理解を禁止した経緯)

ぼくはWebフロントエンドエンジニアなんですが、社会人1年目の頃にベテランエンジニアにこんなセリフを言われたことがあります。

export PATH="***"でパスを通す「おまじない」をすればいい...?「おまじない」って何ですか?え、そもそもパスを通すって何か理解できてる?..........うん、できてなさそうやね。この機会にちゃんと理解しましょ。ちなみにクラークによると魔法を使えるのは優れた技術力を持つ人だけですよ。軽はずみに「おまじない」で事を片付けない方がいいっすよ。

そのベテラン先輩は、ぱっと見冷たく見えるけど初心者にもめっちゃ向き合ってくれる神みたいな人でした。ぼくはこの時に「パスを通す」に限らず、なんとなくの理解で「おまじない」と言って暗記したコマンドを打つのはダメだと学びました。

そんな経験もあって、「なんとなく理解禁止」というシリーズでReactやJavaScriptなどの基礎をブログで少しずつ発信しています!

ちなみにクラークの件は、SF作家アーサー・C・クラークが定義したクラークの三原則のひとつに下記の原則があって...

十分に発達した科学技術は、魔法と見分けがつかない。
Any sufficiently advanced technology is indistinguishable from magic.

これになぞられたセリフでした。「十分な技術力を身につければ魔法のような技を出せるだろうけど、初心者のうちはそんな魔法(おまじない)は使えないでしょ」って事でしょうか。それからこのクラークの三原則の言葉が大好きになりました。ぼくも魔法使いになりたい🧙