「command not found」の対処法 - コマンドが見つからないときの解決策
この記事で解決できること
command not foundの 原因を 30 秒で切り分け られるPATH/hash/sudo/cronの 典型パターン を把握できる- 「インストールしたはずなのに見つからない」を 再発しない形で潰せる
結論(実務の型)
command -v <名前>で存在確認echo $PATHで探索パス確認- パッケージ未導入 / PATH 不足 / hash キャッシュ / sudo secure_path / 入力ミス のどれか
前提(対象環境)
- OS:Ubuntu / Debian 系(apt)。RHEL 系(dnf / yum)も併記
- シェル:bash / zsh
1. 原因はほぼこの 5 つ
command not found の事故原因は次のいずれかにほぼ収束する。
| # | 原因 | 切り分けキー |
|---|---|---|
| 1 | コマンドがインストールされていない | apt-cache search / dnf provides |
| 2 | PATH に実行ファイルがない |
echo $PATH / which -a |
| 3 | シェルの hash キャッシュが古い |
hash -r |
| 4 | sudo の secure_path 制限 |
sudo -V / /etc/sudoers の secure_path |
| 5 | 入力ミス(大文字小文字 / typo) | type / compgen -c |
8 割は ②PATH か ③hash が真因。先にこの 2 つを潰す。
2. 切り分け手順(30 秒テンプレ)
2-1. まず存在確認
$ command -v ansible
- 出力あり → コマンドは見えている。実行できない場合は権限の問題(
Permission denied系を参照) - 出力なし → 2-2 へ
command -v は POSIX 標準。which はディストリ実装依存(Debian の which は単なる exit ステータス返却)で挙動が分かれるため、スクリプト内では command -v を使う。type は alias / function / builtin / file を区別表示できるので調査向き。
2-2. PATH を表示
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
期待するインストール先が PATH に含まれているか を確認する。代表例:
~/.local/bin(pip install --user/pipx)~/bin(Ubuntu の~/.profileで自動追加。ただし bash ログインシェルのみ)/usr/local/bin(手動ビルド系)/snap/bin(snap 経由)
2-3. パッケージから探す
そもそも未インストールなら、提供パッケージを探す。
# Ubuntu / Debian $ apt-cache search ^ansible$ $ /usr/lib/command-not-found ansible # Ubuntu の親切ヒント
# RHEL / Fedora $ dnf provides '*/ansible'
3. ケース別対処
3-1. インストール直後なのに見つからない
シェルが古い実行パスを hash でキャッシュしている。
$ hash -r # bash / zsh いずれも有効 $ rehash # zsh の慣用形
これで直らない場合、PATH に新パッケージのバイナリディレクトリが入っていないか、別ユーザー(root / 他)でインストールしたかのどちらか。
3-2. pip install --user で入れたコマンドが見つからない
インストール先は ~/.local/bin。PATH に追加する。
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc $ source ~/.bashrc
Python の CLI を入れるなら pipx を推奨。pipx ensurepath で PATH 設定までやってくれるため、pip install --user よりも事故が少ない。
3-3. npm install -g のコマンドが見つからない
npm config get prefix でインストール先を確認する。/usr/local ならパーミッションで失敗している可能性、~/.npm-global 等の独自プレフィックスなら bin を PATH に追加する。
$ npm config get prefix $ ls "$(npm config get prefix)/bin"
3-4. 大文字小文字 / typo
Linux はファイル名の 大文字小文字を区別する。
$ Vim file.txt # → command not found $ vim file.txt # OK
候補を一覧:
$ compgen -c vim # vim で始まるコマンドを列挙
3-5. シェルを変えたら見つからない
bash → zsh のような切替時、PATH を書く場所が変わる。
| シェル | ログインシェル | 対話シェル |
|---|---|---|
| bash | ~/.bash_profile → ~/.profile |
~/.bashrc |
| zsh | ~/.zprofile |
~/.zshrc |
~/.profile は POSIX シェルが読む共通設定。~/.bashrc は bash 専用 で zsh からは読まれない。zsh に乗り換えたら ~/.zshrc 側にも PATH 設定を移すこと。
4. PATH を永続化する正しい方法
4-1. 推奨パターン
# ~/.bashrc または ~/.zshrc の末尾 export PATH="$HOME/.local/bin:$PATH"
- 既存 PATH の前後どちらに置くか で優先順位が変わる
- 自作スクリプトを優先したいなら 前
- システムコマンドを優先したいなら 後
やってはいけない:PATH の上書き
# NG: 既存 PATH を消し飛ばす export PATH="$HOME/.local/bin"
ls も cat も sudo も使えなくなる典型事故。必ず $PATH を保持して 追加 すること。
4-2. システムワイドに通したい場合
/etc/profile.d/*.sh を使う。/etc/environment は変数代入のみ(シェル構文不可)。
# /etc/profile.d/myapp.sh export PATH="/opt/myapp/bin:$PATH"
5. sudo / cron で見つからないとき
5-1. sudo で command not found
sudo 実行時の PATH は /etc/sudoers の secure_path で 上書き される。
$ sudo -V | grep -i path Value to override user's $PATH with: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
対策:
# (1) フルパスで叩く(最も確実) $ sudo /home/user/.local/bin/myscript # (2) sudo -E で環境変数を引き継ぐ(secure_path 設定により無視される場合あり) $ sudo -E env "PATH=$PATH" myscript # (3) 恒久対応: visudo で secure_path を編集 $ sudo visudo # Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/user/.local/bin"
secure_path は権限昇格時の PATH 注入攻撃を防ぐためのセキュリティ機構。安易に広げず、必要なディレクトリだけを追加する。
5-2. cron で command not found
cron は 最小限の PATH で起動する。
$ env -i sh -c 'echo $PATH' /usr/bin:/bin
対策(推奨順):
# (1) crontab 内で PATH を明示
PATH=/usr/local/bin:/usr/bin:/bin:/home/user/.local/bin
* * * * * myscript
# (2) スクリプト内でフルパスを使う
* * * * * /home/user/.local/bin/myscript
cron トラブルの 7 割は PATH。次点は標準出力 / 標準エラーの未捕捉。>> /tmp/cron.log 2>&1 を必ず付けて原因を可視化する。
6. コピペ用:診断テンプレート
# 1. 存在確認 command -v ansible # 2. PATH 表示 echo $PATH # 3. hash クリア(インストール直後の鉄板) hash -r command -v ansible # 4. パッケージ検索 apt-cache search ^ansible$ # Debian / Ubuntu dnf provides '*/ansible' # RHEL / Fedora # 5. sudo / cron 経由の確認 sudo command -v ansible sudo -V | grep -i path
やってはいけないこと
PATH=で既存 PATH を消す~/.bash_profileと~/.profileの両方に同じ PATH を書く(一方が無視される)sudo失敗時に脊髄反射でchmod 777