ハードリンクとシンボリックリンクを説明できるようになる
前提
今回はUbuntuで説明します
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.1 LTS"
説明
ハードリンク
ハードリンクとは、「ファイル名と保存されているデータを紐づけるもの」です。
つまり、「保存されたデータに名前を付けるもの」です。
また、ハードリンクは同一ファイルシステムの保存されたデータに紐づける必要があります。
Every file on the Linux filesystem starts with a single hard link. The link is between the filename and the actual data stored on the filesystem.
引用:Red Hatブログ
ハード・リンクは、単にリンクと呼ばれることもあり、 実際のオブジェクトにリンクしていなければなりません。
(ファイルをディレクトリーにコピーするなどの方法で) ディレクトリー内にオブジェクトが作成されると、 ディレクトリーとオブジェクトの間に最初のハード・リンクが設定されます。
引用:IBM:ハードリンク
実演
this is sample
と記載されている sample.txt
を作成します。
$ echo "this is sample" > sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 07:47 sample.txt
$ cat sample.txt
this is sample
$ stat sample.txt
File: sample.txt
Size: 15 Blocks: 8 IO Block: 4096 regular file
Device: 252,0 Inode: 655373 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-23 10:41:50.210205054 +0000
Birth: 2024-10-23 10:41:50.210205054 +0000
このコマンドの裏でLinuxのファイルシステムが、ストレージに保存された this is sample
というデータにsample.txt
という名前を付けるハードリンクを作成しています。
さらに追加でハードリンクを作成してみます。
$ ln sample.txt sampleHardLink
$ ls -li
total 8
655373 -rw-rw-r-- 2 ubuntu ubuntu 15 Oct 23 07:47 sample.txt
655373 -rw-rw-r-- 2 ubuntu ubuntu 15 Oct 23 07:47 sampleHardLink
$ cat sampleHardLink
this is sample
$ stat sampleHardLink
File: sampleHardLink
Size: 15 Blocks: 8 IO Block: 4096 regular file
Device: 252,0 Inode: 655373 Links: 2
Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-24 05:57:54.821199900 +0000
Birth: 2024-10-23 10:41:50.210205054 +0000
これにより、 this is sample
のデータに sampleHardLink
という名前を付けるハードリンクが作成されました。
ls
コマンド出力のinode番号(-rw-rw-r--
の前の数字)も同じ655373
を指し示しています。
さらに、ls
コマンド出力のLinks(-rw-rw-r--
の後の数字)も1
-> 2
に増えています。 (stat
コマンド出力のLinksでも確認可)
ここで sample.txt
を消すとどうなるでしょうか?
試してみましょう。
$ rm sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 09:02 sampleHardLink
sample.txt
の名前だけが消えて、sampleHardLink
の名前だけが残る形となりました。
ls
コマンド出力のLinks(-rw-rw-r--
の後の数字)も2
-> 1
に減っています。
余談ですが、データは自身へのハードリンクが全て削除された時に、ドライブから削除されます。
つまり、自分に付けられた名前(Links)がすべてなくなった時にデータが削除されます。
$ rm sampleHardLink
$ ls -li
total 0
The data is only removed from your drive when all links to the data have been removed.
引用:Red Hatブログ
シンボリック・リンク
シンボリックリンクとは、直訳すると「抽象的なリンク」です。
抽象的なリンクなので、保存されたデータでなくても名前を付けることができます。
ディレクトリやファイルディスクリプタなどの特殊ファイルにも名前を付けることができます。
誤解を恐れずに言うと「名前に付ける名前」みたいなものです。
シンボリックリンクは複数のファイルシステムにまたがることができます。
Commonly referred to as symbolic links, soft links link together non-regular and regular files.
They can also span multiple filesystems.
引用:Red Hatブログ
シンボリック・リンクは、ファイルに含まれるパス名であり、ソフト・リンクとも呼ばれます。
実演
ハードリンクと同じ状況にします。
this is sample
と記載されているsample.txt
を作成します。
$ echo "this is sample" > sample.txt
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 03:09 sample.txt
$ cat sample.txt
this is sample
$ stat sample.txt
File: sample.txt
Size: 15 Blocks: 8 IO Block: 4096 regular file
Device: 252,0 Inode: 655373 Links: 1
Access: (0664/-rw-rw-r--) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2024-10-23 10:51:14.361429275 +0000
Modify: 2024-10-23 10:41:50.210205054 +0000
Change: 2024-10-23 10:41:50.210205054 +0000
Birth: 2024-10-23 10:41:50.210205054 +0000
それではシンボリックリンクを貼ってみます。
$ ln -s sample.txt sampleSymbolicLink
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655375 lrwxrwxrwx 1 ubuntu ubuntu 10 Oct 23 10:50 sampleSymbolicLink -> sample.txt
$ cat sampleSymbolicLink
this is sample
$ stat sampleSymbolicLink
File: sampleSymbolicLink -> sample.txt
Size: 10 Blocks: 0 IO Block: 4096 symbolic link
Device: 252,0 Inode: 655375 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2024-10-23 10:50:28.746456839 +0000
Modify: 2024-10-23 10:50:26.815458100 +0000
Change: 2024-10-23 10:50:26.815458100 +0000
Birth: 2024-10-23 10:50:26.815458100 +0000
シンボリックリンクのリンク先が sample.txt
であることがわかります。
ls
コマンドの出力からLinksは1
のまま変わらず、inode番号も655373
と655375
で異なります。
シンボリックリンクを削除しても元のファイル等は削除されません。
$ rm sampleSymbolicLink
ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
$ cat sample.txt
this is sample
シンボリックリンクはディレクトリにも貼ることができます。
$ ln -s /dev/fd/ sampleDir
ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655376 lrwxrwxrwx 1 ubuntu ubuntu 8 Oct 23 11:04 sampleDir -> /dev/fd/
$ ls -li sampleDir/
total 0
36771 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 0 -> /dev/pts/0
36772 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 1 -> /dev/pts/0
36773 lrwx------ 1 ubuntu ubuntu 64 Oct 23 11:04 2 -> /dev/pts/0
36774 lr-x------ 1 ubuntu ubuntu 64 Oct 23 11:04 3 -> /proc/18762/fd
36775 lr-x------ 1 ubuntu ubuntu 64 Oct 23 11:04 63 -> 'pipe:[24058]'
ちなみに、シンボリックリンクは実態がないものにも貼ることができます。
$ ln -s notExist sampleNotExist
$ ls -li
total 4
655373 -rw-rw-r-- 1 ubuntu ubuntu 15 Oct 23 10:41 sample.txt
655376 lrwxrwxrwx 1 ubuntu ubuntu 8 Oct 23 11:04 sampleDir -> /dev/fd/
655377 lrwxrwxrwx 1 ubuntu ubuntu 8 Oct 23 11:15 sampleNotExist -> notExist
$ cat sampleNotExist
cat: sampleNotExist: No such file or directory
$ stat sampleNotExist
File: sampleNotExist -> notExist
Size: 8 Blocks: 0 IO Block: 4096 symbolic link
Device: 252,0 Inode: 655377 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ ubuntu) Gid: ( 1000/ ubuntu)
Access: 2024-10-25 04:29:56.213534050 +0000
Modify: 2024-10-23 11:15:32.574498481 +0000
Change: 2024-10-23 11:15:32.574498481 +0000
Birth: 2024-10-23 11:15:32.574498481 +0000
まとめ
シンボリックリンクとハードリンクについてまとめてみました。
少しでも学びになってもらえれば嬉しいです。
参考
レバテック開発部の公式テックブログです! レバテック開発部 Advent Calendar 2024 実施中: qiita.com/advent-calendar/2024/levtech
Discussion