「command not found」の対処法 - コマンドが見つからないときの解決策

「command not found」の対処法 - コマンドが見つからないときの解決策

この記事で解決できること

  • command not found原因を 30 秒で切り分け られる
  • PATH / hash / sudo / cron典型パターン を把握できる
  • 「インストールしたはずなのに見つからない」を 再発しない形で潰せる

結論(実務の型)

  1. command -v <名前> で存在確認
  2. echo $PATH で探索パス確認
  3. パッケージ未導入 / 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 sudosecure_path 制限 sudo -V / /etc/sudoerssecure_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/binpip 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. シェルを変えたら見つからない

bashzsh のような切替時、PATH を書く場所が変わる。

シェル ログインシェル 対話シェル
bash ~/.bash_profile~/.profile ~/.bashrc
zsh ~/.zprofile ~/.zshrc

~/.profile は POSIX シェルが読む共通設定。~/.bashrcbash 専用 で zsh からは読まれない。zsh に乗り換えたら ~/.zshrc 側にも PATH 設定を移すこと。

4. PATH を永続化する正しい方法

4-1. 推奨パターン

# ~/.bashrc または ~/.zshrc の末尾
export PATH="$HOME/.local/bin:$PATH"
  • 既存 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/sudoerssecure_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

次に読む