エラーの内容
ln: failed to create symbolic link '/usr/local/bin/node': File exists
ln -s でシンボリックリンクを作成しようとしたら、この壁にぶつかった。対象のパスに何かがすでに存在している — ファイル、ディレクトリ、またはどこにも指していない古いシンボリックリンクかもしれない。明示的に指示しない限り、ln は上書きしない。
なぜこうなるのか
宛先パス(ここでは /usr/local/bin/node)がすでに使われている。よくある原因はいくつかある:
- 異なる方法で同じツールを二重にインストールした — たとえば nvm とシステムのパッケージマネージャーを併用した場合など
- 古いインストールの残骸となったシンボリックリンクがまだ残っている
- セットアップスクリプトがクリーンアップなしに再実行された
- シンボリックリンクではなく、実際のバイナリがすでにそのパスに存在している
ステップ 1 — 現状を確認する
まだ何も触らないこと。まず何が存在しているかを把握する:
ls -la /usr/local/bin/node
表示される可能性のある3つのパターン:
# 有効なシンボリックリンク(正しい場所を指している)
lrwxrwxrwx 1 root root 30 Mar 12 2024 /usr/local/bin/node -> /home/user/.nvm/versions/node/v20.0.0/bin/node
# 壊れたシンボリックリンク(リンク先が削除されている)
lrwxrwxrwx 1 root root 30 Mar 12 2024 /usr/local/bin/node -> /home/user/.nvm/versions/node/v18.0.0/bin/node
# 実際のバイナリファイル
-rwxr-xr-x 1 root root 89654312 Jan 5 10:22 /usr/local/bin/node
シンボリックリンクの場合、リンク先がまだ存在するか確認する:
readlink -f /usr/local/bin/node
出力が空、またはパスが存在しない場合はシンボリックリンクが壊れている。置き換えても安全だ。
ステップ 2 — -sf で強制上書きする
最も手っ取り早い解決策:-f フラグを使えば、既存のものを削除して新しいシンボリックリンクを一度に作成できる。
ln -sf /path/to/new/target /usr/local/bin/node
-s = シンボリック、-f = 強制上書き。nvm の Node v20.11.0 を使った具体例:
ln -sf /home/user/.nvm/versions/node/v20.11.0/bin/node /usr/local/bin/node
root 権限が必要な場合は sudo を頭に付ける:
sudo ln -sf /home/user/.nvm/versions/node/v20.11.0/bin/node /usr/local/bin/node
ステップ 3 — 手動で削除してからリンクし直す(-f では対処できない場合)
-f が効かないケースが一つある:対象がディレクトリの場合だ。まず手動で削除する必要がある。
# 種類を確認する
file /usr/local/bin/node
# ファイルまたはシンボリックリンクを削除する
sudo rm /usr/local/bin/node
# シンボリックリンクを作成する
sudo ln -s /path/to/target /usr/local/bin/node
ディレクトリの場合は、適切な削除コマンドを使う:
# 空のディレクトリ
sudo rmdir /usr/local/bin/node
# 空でないディレクトリ(実行前によく確認すること)
sudo rm -r /usr/local/bin/node
sudo ln -s /path/to/target /usr/local/bin/node
ステップ 4 — 修正を確認する
すべて正しく設定されているか確認するための3つの簡単なチェック:
ls -la /usr/local/bin/node
readlink -f /usr/local/bin/node
node --version
3つすべてが一致しているはずだ。期待される出力:
lrwxrwxrwx 1 root root 52 May 5 02:14 /usr/local/bin/node -> /home/user/.nvm/versions/node/v20.11.0/bin/node
/home/user/.nvm/versions/node/v20.11.0/bin/node
v20.11.0
2つのインストールが同じパスを取り合っている場合の対処
nvm と apt が両方 /usr/local/bin/node を所有しようとしている。このままでは互いに干渉し続ける。クリーンな解決策:どちらか一方を選んでもう一方を削除する。
# Ubuntu/Debian — システムパッケージを削除する
sudo apt remove nodejs
# CentOS/RHEL
sudo dnf remove nodejs
そのまま nvm に管理を任せる。あるいはシステムパッケージを残したまま、バイナリのインストール先にシンボリックリンクを向け直す:
which node # システムバイナリの実際の場所を調べる
sudo ln -sf $(which node) /usr/local/bin/node
壊れたシンボリックリンクをまとめてクリーンアップする
インストールスクリプトが失敗した場合、複数の壊れたシンボリックリンクが残っているかもしれない。まずすべて見つけ出す:
# /usr/local/bin 内の壊れたシンボリックリンクをすべてリストアップする
find /usr/local/bin -maxdepth 1 -type l ! -exec test -e {} \; -print
削除する前にリストを確認すること。その後、必要に応じてリンクを張り直すか削除する。
再発を防ぐために
- スクリプトでは
-sfをデフォルトにする(-sだけは使わない)。べき等性があるため、スクリプトを再実行しても既存のリンクでエラーにならない。 - リンク作成前にガード処理を入れる:インストールスクリプトの
ln呼び出し前に[ -e "$target" ] && rm "$target"を追加する。 - ツールごとにパッケージマネージャーは一つに絞る。Node に nvm と apt を混在させる(または Python に pyenv と pip を混在させる)ことが、このエラーの原因になる。
- Debian 系システムでは、複数バージョンのツールには
update-alternativesを使う — シンボリックリンクの管理を自動化できるので、手動管理が不要になる:
sudo update-alternatives --install /usr/bin/node node /usr/local/bin/node 100

