プログラミングの学習を進めるにつれて、Linux特有の「パスを通す」の意味をしっかり理解しないと、環境構築で詰むケースが増えた。 よって、あらためて「パスを通す」の意味を整理した。
環境
なぜ wget コマンドは wget と打つだけで実行されるのか?
wget
とは、引数にURLを指定することでファイルをダウンロードできるコマンドのこと。普段は意識せずwget URL
と打つだけで実行できるが、これは厳密に言うと以下のことをしている。
/usr/bin/wget URL
ただ、こんなコマンドをいちいち覚えていられない。だから「ある方法」を使ってwget
と叩くだけで/usr/bin/wget URL
と同様のことを実現している。その方法が、この記事で解説する「パスを通す」という方法です。
では、なぜwget
コマンドを叩くだけでいいのか?理由は、「パスの通ったディレクトリ」に実行ファイルが保存されているから。パスの通ったディレクトリに保存されている実行ファイルは、./
などと文頭につけなくても、wgetだけで実行できるようになる。
たとえば、Linuxの/usr/bin
ディレクトリには、Linuxで使えるwgetコマンドの実行可能ファイルが入っている。(Linuxのディストリビューションによっては違う名前のディレクトリかも)
binというのはbinaryを意味し、機械語という意味だ。/usr/bin/
に入っている実行可能ファイルは、すべてパスを指定しなくてもファイル名で実行できる。いわば、特殊な権利を与えられた、特別なディレクトリということになる。
以下は、wget
コマンドと同じ働きをする。
# これでも動く /usr/bin/wget URL # いつもの wget URL
繰り返すが、wgetコマンドがパスを指定しなくても動く理由は、/usr/bin/
というディレクトリにパスが通っているから。
パスが通ったディレクトリを見る方法
では、どうやってその「パスが通ったディレクトリ」を知ればいいのか?
次のコマンドで確認できる。
echo $PATH
$PATHという変数の中に、パスが通ったディレクトリの情報が記されている。それをechoコマンドでコマンドラインに出力している。
結果
/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.nvm/versions/node/v10.14.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:~/mybin
このように、パスが通ったディレクトリはひとつではなく、たくさんあって、:
で区切られる。
ただ、これでは見づらいので見やすく出力する。
echo $PATH | sed -e 's/:/\n/g'
/home/vagrant/.yarn/bin /home/vagrant/.config/yarn/global/node_modules/.bin /home/vagrant/.yarn/bin /home/vagrant/.config/yarn/global/node_modules/.bin /home/vagrant/.yarn/bin /home/vagrant/.config/yarn/global/node_modules/.bin /home/vagrant/.yarn/bin /home/vagrant/.config/yarn/global/node_modules/.bin /home/vagrant/.yarn/bin /home/vagrant/.config/yarn/global/node_modules/.bin /home/vagrant/.nvm/versions/node/v10.14.2/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games ~/mybin
これらのディレクトリに、それぞれパスが通っている。ここに記載のあるディレクトリに実行可能ファイルを置くと、絶対パスを指定せずとも、ファイル名だけで実行が可能になる。
ためしに、/usr/bin/
を見てみると、たくさんの実行可能ファイルが保存されていることが確認できる。
ls /usr/bin/
NF gpic python3-jsondiff VGAuthService gprof python3-jsonpatch '[' gresource python3-jsonpointer aa-enabled groff python3-jsonschema aa-exec grog python3.6 acpi_listen grops python3.6m add-apt-repository grotty python3m addpart groups ranlib addr2line growpart rcp apport-bug grub-editenv rdma ~~~ # たくさんあるので省略
なお、もし同じ名前の実行可能ファイルがあった場合は、echo $PATH
の出力結果の、左側のディレクトリに置いてあるものが優先される。
また、自分が新しく作成した実行可能ファイルを、既存のパスが通っているディレクトリに置くのはNG。 なぜなら、他の実行可能ファイルと混ざってしまい、自分のファイルがどれで、元からあったプログラムがなんなのかわからなくなるため。
新しく自分でディレクトリを作成し、そのディレクトリのパスを通してあげることで使用したほうがいい。
ディレクトリにパスを通す方法
試しに、こんなことをしてみる。
ここからの流れは以下のサイトを参考にさせていただく。
c言語のファイルを作成。
vim moji.c
以下を追記。
#include <stdio.h> void main() { printf("あなたご飯にする?"); printf("お風呂にする?\n"); printf("それとも、タ・ワ・シ?"); }
vimは:wq
で上書き保存。
gcc moji.c -o moji
実行してみる。
./moji
すると、
./moji あなたご飯にする?お風呂にする? それとも、タ・ワ・シ?vagrant@ubuntu-bionic:~$
改行がおかしいが、とりあえずコマンドは実行される。
次に、mybin
というディレクトリを作成。
mkdir ~/mybin
~/
でホームディレクトリに作成している。
さきほど作った実行可能ファイルをこのディレクトリにコピー。
cp moji ~/mybin/.
そしてついに、このディレクトリにパスを通す!
export PATH="$PATH:~/mybin"
exportコマンドを使っている。 これで、PATH変数の中身を書き換えて、自分が作ったディレクトリをPATH変数の中に追加した。
さらに詳しくいうと、"$PATH:~/mybin"
の$PATH
には、以前まで設定されていたPATHが書かれているため、:
で区切り、新しくパスを通したいディレクトリを登録している。
より具体的にすると、もともとPATH変数に保存されていた情報
/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.yarn/bin:/home/vagrant/.config/yarn/global/node_modules/.bin:/home/vagrant/.nvm/versions/node/v10.14.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
この末尾に、:~/mybin
を追記している。
参考: 80.環境変数の話
次に、$PATH
を確認してみる。
echo $PATH | sed -e 's/:/\n/g'
すると、下のほうに登録されているのがわかる。
~ 省略 ~ /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /usr/games /usr/local/games # あった! ~/mybin
これで、ファイル名だけで実行されるか確認する。
moji あなたご飯にする?お風呂にする? それとも、タ・ワ・シ?vagrant@ubuntu-bionic:~$
どのディレクトリにいても、ファイル名だけで実行できるようになった。
永続的に値を設定したい場合
上記の設定方法だと、CUI環境を一旦終わらせると、変数の情報が元に戻る。
ためしに、vagrantを一旦終わらせて再度ログインし、moji
とコマンドを打ってみる。
moji => Command 'moji' not found
実行できなかった。
永続化するには、ホームディレクトリにある.bashsrc
もしくは.bash_profile
にディレクトリのパスを通す設定を書く。
vim .bash_profile
でファイルを開き、
# テスト export PATH="$PATH:~/mybin"
と書く。 そしてsourceコマンドで設定を再読み込みする。
source ~/.bash_profile
そしてmojiコマンドを打ってみると
moji あなたご飯にする?お風呂にする? それとも、タ・ワ・シ?vagrant@ubuntu-bionic:~$
実行された!
なぜこれができるかというと、Linuxでは、シェル(ここではbash)の起動時に~/.bash_profile
を設定ファイルとして読み込むため。