【Linux】lnコマンドとシンボリックリンクの使い方|引数の順序・リンク切れ・ハードリンク

【Linux】lnコマンドとシンボリックリンクの使い方|引数の順序・リンク切れ・ハードリンク Linux

シンボリックリンクは、Windowsの「ショートカット」に近い、別の場所にあるファイルやディレクトリを指し示す特別なファイルです。ln -sコマンドで作成し、「設定ファイルの実体は1つにして複数の場所から参照する」「バージョン付きディレクトリにcurrentという固定名でアクセスする」など、Linuxの運用のあちこちで使われています。

つまずきやすいのは、ln -s 実体 リンク名という引数の順序(逆に覚えている人が多い)と、相対パスで作ったリンクは移動すると壊れることです。この記事では、実機のLinux(WSLのDebian)でリンクを作成・破壊・張り替えしながら、lnの使い方を整理します。

先に結論

  • 作成はln -s 実体のパス リンク名。「本物が先、あだ名が後」です。
  • リンク経由の読み書きは実体に届きますrm リンクリンクだけを消します。
  • 実体を消すとリンク切れになり、No such file or directoryになります。
  • 相対パスで作ったリンクは、リンクを移動すると壊れます。移動するなら絶対パスで作ります。
  • 張り替え(上書き)はln -sf 新実体 リンク名です。
  • -sなしのハードリンクは実体と一心同体で、元を消しても生き残ります。

リンクの確認に使うls -lの読み方はchmodとパーミッション、リンクの検索はfindコマンド、ほかの基本はよく使うLinuxコマンドまとめもあわせて参考になります。

スポンサーリンク

シンボリックリンクを作る(ln -s)

基本はln -s 実体のパス リンク名です。「実体(本物)が先、リンク名(あだ名)が後」という順序を必ず覚えてください。作成後はls -lで確認できます。

作成と確認
# 実体ファイル
echo "real data" > target.txt

# シンボリックリンクを作る(実体が先、リンク名が後)
ln -s target.txt mylink

# ls -l で確認(先頭が l、-> で指し先が表示される)
ls -l mylink
# lrwxrwxrwx ... mylink -> target.txt
順序は「本物 → あだ名」

実機でも、ln -s target.txt mylinkで作成したリンクは、ls -l先頭がl(リンクの印)となり、mylink -> target.txtと指し先が矢印で表示されました。引数の順序はcpmvと同じ「元 → 先」の感覚で、「実体(すでに在るもの)→ リンク名(これから作るもの)」です。逆にすると「リンク名という名の実体」を指す壊れたリンクができてしまいます。迷ったら「cp 元 先と同じ順」と覚えるのが確実です。ディレクトリへのリンクも同じ書き方で作れます(ln -s /var/www/app-v2 currentなど)。

リンク経由の読み書き・rmの挙動

リンクは「透明な窓」のように働きます。リンクを読めば実体が読め、リンクに書けば実体に書き込まれます。そしてrm リンクは、窓(リンク)だけを消し、実体は残します

読み書きとrm
# リンク経由で読む → 実体の中身が見える
cat mylink        # real data

# リンク経由で書く → 実体に反映される
echo "added" >> mylink
tail -1 target.txt   # added(実体に書かれている)

# リンクを rm しても、実体は無事
rm mylink
cat target.txt    # real data(残っている)

実機でも、cat mylinkで実体の中身が読め、>> mylinkで追記した内容は実体target.txtに反映されました。そしてrm mylinkを実行しても、消えるのはリンクだけで実体は無事でした。「リンクを消したら本体まで消えるのでは」と心配する必要はありません。逆に言えば、本体を消したいときにリンクを消しても意味がない、ということでもあります。

リンク切れ(実体を消すとどうなるか)

逆に、実体のほうを消すと、リンクは「指し先のない矢印」=リンク切れになります。見た目は残っているのに、アクセスするとエラーになります。

リンク切れの再現
ln -s target.txt mylink2
rm target.txt          # 実体を削除

# リンクは残って見えるが…
ls -l mylink2
# lrwxrwxrwx ... mylink2 -> target.txt(矢印は残る)

# アクセスするとエラー
cat mylink2
# cat: mylink2: No such file or directory
「ファイルはあるのにNo such file」の正体

実機で確認したところ、実体を削除してもリンク自体はls -lmylink2 -> target.txtと表示されたままでしたが、cat mylink2No such file or directoryになりました。これがリンク切れ(dangling symlink)です。「lsでは見えるのに開くと存在しないと言われる」不思議な状態は、ほぼこのリンク切れが原因です。指し先はls -lの矢印かreadlink リンク名で確認できます。リンク切れをまとめて探したいときはfind . -xtype lが使えます。実体を復元するか、後述の-sfで正しい実体に張り替えて直します。

【最重要】相対パスの罠

もっとも実害の大きい罠がこれです。相対パスで作ったリンクは、「リンク自身の場所」を基準に解決されるため、リンクを別のディレクトリへ移動すると壊れます

相対パスと絶対パスの違い
# 相対パスでリンクを作成(この場所では動く)
ln -s sub/data.txt badlink
cat badlink            # OK(カレントに sub/ があるため)

# リンクを別ディレクトリへ移動すると…
mv badlink moved/
cat moved/badlink
# cat: moved/badlink: No such file or directory ← 壊れた!

# 絶対パスで作れば、どこへ移動しても切れない
ln -s /tmp/lt/sub/data.txt goodlink
mv goodlink moved/
cat moved/goodlink     # sub data(正常に読める)
移動するリンクは絶対パスで作る

実機で確認したところ、ln -s sub/data.txt badlinkと相対パスで作ったリンクは、その場では正常に読めましたが、別ディレクトリへmvした瞬間にNo such file or directoryになりました。相対パスのリンクは「リンクが置かれている場所から見たsub/data.txt」を探すため、リンクが動くと基準もずれて壊れるのです。一方、絶対パス(/から始まるフルパス)で作ったリンクは、移動しても正常に読めました。使い分けの目安は、「実体とリンクをディレクトリごと一緒に移動する(プロジェクト内のリンクなど)なら相対パス」「リンク単体を移動したり、場所が固定の実体を指すなら絶対パス」です。迷ったら絶対パスが安全です。

張り替える(ln -sf)

既存のリンクを別の実体へ向け直すには-f(force)を足してln -sfを使います。デプロイで「currentを新バージョンに切り替える」定番の操作です。

-sf で張り替え
echo "v1" > app-v1.txt
echo "v2" > app-v2.txt

# current は最初 v1 を指す
ln -s app-v1.txt current
cat current      # v1

# -sf で v2 に張り替え(既存リンクを上書き)
ln -sf app-v2.txt current
cat current      # v2

実機でも、ln -sf b.txt curで既存リンクが張り替わり、catの結果がv1からv2に切り替わりました。-fなしで同名リンクを作ろうとすると「File exists」で失敗するため、張り替えは-sfとセットで覚えます。リリースのたびにln -sf /var/www/app-v2 currentのように切り替えれば、参照側は常にcurrentを見るだけで済み、切り戻しも一瞬です。

ハードリンクとの違い(-sなし)

-sを付けないlnハードリンクを作ります。シンボリックリンクが「矢印」なのに対し、ハードリンクは同じ実体に付けたもう1つの名前です。性質が大きく違います。

ハードリンクの挙動
echo "hard" > h.txt
ln h.txt hlink        # -s なし=ハードリンク

# 2つの名前は同じ実体(inode番号が同一)
ls -i h.txt hlink
# 12345 h.txt
# 12345 hlink   ← 同じ番号

# 元の名前を消しても、実体は残る
rm h.txt
cat hlink             # hard(読める!)
ハードリンクは元を消しても生き残る

実機で確認したところ、ln h.txt hlinkで作った2つの名前はls -iのinode番号が同一(=同じ実体)で、rm h.txtで元の名前を消してもhlinkから中身が読めました。ハードリンクは「実体への参照カウント」を増やす仕組みで、すべての名前が消えるまで実体は残ります。シンボリックリンクとの主な違いは、①元を消してもリンク切れしない、②別のディスク(パーティション)をまたげない、③ディレクトリには作れない、④どれが「本物」か区別がない、の4点です。日常的に使うのは圧倒的にシンボリックリンク(-s)で、「lnは基本-sを付ける」と覚えて問題ありません。

主な書き方一覧

lnとリンク操作をまとめます。

書き方 働き
ln -s 実体 リンク名 シンボリックリンク作成(本物→あだ名)
ln -sf 実体 リンク名 既存リンクを張り替え
ls -l l->で指し先を確認
readlink リンク名 指し先のパスを表示
rm リンク名 リンクだけ削除(実体は無事)
find . -xtype l リンク切れを探す
ln 実体 名前(-sなし) ハードリンク(同一実体の別名)

よくある失敗

引数の順序を逆にする

ln -s リンク名 実体は誤りです。「実体が先、リンク名が後」(cpと同じ元→先)です。

相対パスで作ったリンクを移動して壊す

相対リンクはリンクの場所基準で解決されます。移動するなら絶対パスで作ります。

リンク切れに気づかない

lsには見えても実体が無いことがあります。catreadlinkfind -xtype lで確認します。

File existsで作成に失敗する

同名のリンクが既にあります。張り替えるなら-sfを使います。

リンクを消せば本体も消えると思う

rm リンクはリンクだけを消します。本体は実体のパスをrmします。

よくある質問

Qシンボリックリンクはどう作りますか?
Aln -s 実体のパス リンク名で作成します。順序は「本物(すでに在るもの)が先、リンク名(これから作るもの)が後」で、cp 元 先と同じ感覚です。作成後はls -lで、先頭のl->による指し先表示を確認できます。
Qリンクを削除したら本体も消えますか?
A消えません。rm リンク名で消えるのはリンク(矢印)だけで、実体はそのまま残ります。実機でも、リンク削除後に実体が無事であることを確認しています。逆に、実体のほうを消すとリンクは「リンク切れ」になり、アクセス時にNo such file or directoryになります。
Qlsでは見えるのに開くとNo such fileと言われます。
Aリンク切れ(実体が削除・移動されたシンボリックリンク)です。ls -l->の先やreadlink リンク名で指し先を確認し、実体を戻すかln -sf 正しい実体 リンク名で張り替えてください。リンク切れの一括検索はfind . -xtype lが便利です。
Qリンクを移動したら壊れました。なぜですか?
A相対パスで作ったリンクは「リンクが置かれた場所」を基準に指し先を解決するため、リンクを移動すると基準がずれて壊れます。実機でも、相対リンクの移動直後にNo such fileになることを確認しています。リンク単体を移動する可能性があるなら、絶対パスで作成してください。
Qシンボリックリンクとハードリンクの違いは?
Aシンボリックリンク(-sあり)は実体を指す「矢印」で、実体を消すとリンク切れになります。ハードリンク(-sなし)は同じ実体に付けた別名(inodeが同一)で、元の名前を消しても実体が残ります。ただしハードリンクは別パーティションをまたげず、ディレクトリにも作れません。通常は-sを使えば十分です。

まとめ

  • 作成はln -s 実体 リンク名(本物が先・cpと同じ元→先)。
  • リンク経由の読み書きは実体に届き、rm リンクリンクだけ消します。
  • 実体を消すとリンク切れlsに見えても開けなくなります。
  • 相対パスのリンクは移動で壊れる。移動するなら絶対パスで作ります。
  • 張り替えはln -sf、ハードリンク(-sなし)は元を消しても生き残ります。

シンボリックリンクは、「実体は1つ・参照は好きな場所から」を実現するLinuxの便利な仕組みです。「順序は本物→あだ名」「移動するなら絶対パス」の2点を押さえれば、設定ファイルの共有からデプロイの切り替えまで、安心して活用できます。