コマンドが見つからない
中段 / 目安 30分
事務局の朝、鴫原さんが端末の前で固まっています。画面には同じ行がいくつも並んでいます。
プレーンテキスト
-bash: ls: command not found
-bash: grep: command not found「昨日、商店街のツールを楽に呼べるようにしたくてな。設定を1行足したんだ。そうしたら今朝ログインし直したとたん、これだ。ls すら打てん」
鴫原さんが足したかったのは /opt/yumesaku/bin にある shopctl という自前のツールです。フルパスで打てば動くのに、名前だけでは動かない。それが面倒で設定をいじった、というところまでは分かりました。
幸い、いま開いているこの端末はまだ壊れる前の状態を持っています。ログインし直した瞬間に壊れる、という形の故障です。直す猶予があるうちに直すのが今回の仕事です。
シェルはコマンドをどう見つけているか
ls と打ったとき、シェルは ls という名前のファイルを探しに行きます。どこを探すかを決めているのが PATH という環境変数です。中身を見てみます。
ターミナル
echo $PATHコロンで区切られたディレクトリの列が出ます。シェルはこの列を左から順に見て、最初に見つかった実行ファイルを使います。列に入っていない場所は、いくら実行可能なファイルが置いてあっても探されません。だから command not found は「そんなファイルは無い」ではなく、「探す場所に無い」という意味です。
あるコマンドが実際にどれとして解決されているかは which で分かります。
ターミナル
which ls
which shopctl見つからないときは which が何も出さず、終了ステータスが 0 以外になります。
設定は毎回読み直される
いま動いている端末の PATH を書き換えても、その端末を閉じれば消えます。恒久的にしたいときは、シェルが起動のたびに読むファイルに書きます。bash なら /root/.bashrc です。ログインすると /root/.profile が .bashrc を読み込む作りになっています。
ここに書くときの落とし穴が1つあります。次の2行は、見た目は似ていてもまったく違います。
ターミナル
export PATH=/opt/yumesaku/bin
export PATH="$PATH:/opt/yumesaku/bin"上は、それまでの PATH を捨てて新しい値に置き換えます。/usr/bin も /bin も列から消えるので、ls も grep も見つからなくなります。下は、いまの値の後ろに1つ足しています。追加したいときは必ず $PATH を含めてください。
設定ファイルを直したら、読み直させます。
ターミナル
source /root/.bashrcあるいは、新しいログインシェルを1つ起こして確かめる方法もあります。壊れた設定を自分の端末に持ち込まずに検証できるので、こちらのほうが安全です。
ターミナル
bash -lc 'echo $PATH'-l はログインシェルとして起動する指定、-c は続く1行を実行して終わる指定です。設定ファイルを直したかどうかは、これで確かめられます。
完成条件
- ログインし直しても
lsやgrepが名前だけで動くこと - 同じく、
shopctlがフルパスなしで動くこと - 直したのは設定ファイルそのものであること。いま開いている端末だけを直しても、ログインし直せば元に戻ります
進め方
まず echo $PATH と cat /root/.bashrc で、何が起きているかを目で見てください。原因が分かってから手を入れます。編集には nano が使えます。この機械に vim は入っていません。
ヒントは3段階で、①方針、②使うコマンド、③部分解の順に出ます。1つも開けずに通せたら、その問題は自分のものです。
課題
- 原因が /root/.bashrc の PATH の書き方にあることを突き止めること
- ログインシェルでも ls・grep・cat などの標準コマンドが名前だけで動くこと
- /opt/yumesaku/bin/shopctl が shopctl という名前だけで動くこと
- 直すのは設定ファイル。いま開いている端末の PATH だけを書き換えても直ったことにはなりません
ヒント
前のヒントを開くと次が開きます。開かずに解けると未開封クリアです