【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【大阪 / 横浜】インフラ / サーバーサイドエンジニア募集中!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【導入実績 500社以上】AWS 構築・運用保守・監視サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【CentOS 後継】AlmaLinux OS サーバー構築・移行サービス

【WordPress 専用】クラウドサーバー『ウェブスピード』

【WordPress 専用】クラウドサーバー『ウェブスピード』

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【格安】Webサイト セキュリティ自動診断「クイックスキャナー」

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【低コスト】Wasabi オブジェクトストレージ 構築・運用サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【予約システム開発】EDISONE カスタマイズ開発サービス

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【100URLの登録が0円】Webサイト監視サービス『Appmill』

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【中国現地企業に対応】中国クラウド / サーバー構築・運用保守

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

【YouTube】ビヨンド公式チャンネル「びよまるチャンネル」

「シンボリックリンクの削除」に unlinkコマンドを使う理由

こんにちは。システムソリューション部所属 なかともです。
最近、SSL証明書の更新のためシンボリックリンクに触れる機会がありました。

その際に、改めてシンボリックリンクについて調べていると「シンボリックリンクの削除にunlink コマンドを使う」という情報が多く見受けられます。
ただし、以下のような点が気になりました。

「 シンボリックリンクの削除には”比較的”安全なだけで、間違えると普通に危ないのを説明してない事がある」
「コマンドやオプションの使い方が人によって微妙に違う」
「 たまにシンボリックリンクの削除用のコマンドと誤解している人もいる

というわけで当記事では、
「シンボリックリンクの削除」にunlinkコマンドを使う理由や使い方がわかるよう、どのようなコマンドなのかも含めてご説明したいと思います。

実行環境

・OS:Ubuntu 20.04.5 LTS (WSL2環境)
・Shell:bash
・ロケールを日本語に変更

注意事項

当記事はLinuxにおける主要ディストリビューションであるRHEL系・Debian系における内容となっております。

SolarisなどのUNIX系ではunlinkコマンドの仕様に違いがあるためです。

unlink コマンドはファイルを削除するためのコマンド

un "link" と書かれているので シンボリック"リンク" を消すコマンドと誤解している方もいるかもしれませんが、

「シンボリックリンクも消せるだけで、本来はファイルを削除するためのコマンド」となっています。

Ubuntuでmanを叩いて確認してみると、下記のような説明がなされています。

$man unklink
UNLINK(1) ユーザーコマンド UNLINK(1)
名前
unlink - unlink 関数を呼び出し指定されたファイルを削除する
書式
unlink FILE
unlink OPTION
説明
指定した FILE を削除するために unlink 関数を呼び出します。
--help この使い方を表示して終了する
--version
バージョン情報を表示して終了する
※以下省略

説明の通り「指定されたファイルを削除する」コマンドと書かれています。

シンボリックリンクを消すためのコマンドではないため、普通に実体のファイルも消せるということです。

ファイルを削除する際の内部的な動作は rm コマンドと同じ

説明 指定した FILE を削除するために unlink 関数を呼び出します。

上記(man)で説明される「unlink 関数」とは「unlink」という、内部の根幹であるLinuxカーネルの機能を実行させる「システムコール」の事を指しています。
カーネルはこのシステムコールを受けて、指定されたファイルのハードリンクを削除することで、実態としてデータが消えます。

詳細についてはLinuxのファイル構造とハードリンク・シンボリックリンクの根本的かつ長い説明になるので割愛しますが、
要するに内部的にデータを削除する機能を呼び出すもので、このシステムコールは rm コマンドも使用しています。

ディレクトリを削除する「rmdir」システムコールと、ファイルを削除する「unlink」システムコールを使い
そこに色々なオプション機能を盛り込んだのが rmコマンドです。

つまり、ファイルを削除する事においては rmコマンドとunlinkコマンドはLinuxカーネルの内部的には同じ事をしています。

ファイルを消すコマンドという認識(危機感)を強くもっておく事が、安全に繋がって良いと筆者は考えます。

検証として削除用の実体ファイルを作って動作を確認する

検証のため「Testdate」というファイルを検証環境に用意します。

$ touch Testdate
$ ls -l
合計 0
-rw-r--r-- 1 ubuntu ubuntu 0 9月 16 17:10 Testdate

ここで、unlink を使って実体ファイルを指定すると削除できる事が確認できます。

$ unlink Tstdate
$ ls -l
合計 0

このように実体ファイルを削除するコマンドなので、シンボリックリンクを消そうとして元のリンク元ファイルを指定してしまうと当然消えます。

また、rm コマンドと違って -i オプションのような確認を出す誤操作予防機能は持っていないため要注意です。

rm コマンドとどう違うの?

unlink コマンドはディレクトリを消せず、ディレクトリ内のファイルを再帰的には消せない

これがシンボリックリンクを消す際に、このコマンドを使うことが一般的に推奨される理由です。

rmコマンドで誤って「リンク元ディレクトリ」や「シンボリックリンク先の配下を指定」してしまった際の削除事故を防げるからです。

どういうことなのかを、失敗実例で説明するため
「TestDir」というディレクトリとそれに対するシンボリックリンク「TestDir-link」を用意しました。
「TestDir」の配下には、検証用のテキストデータを3ファイル配置しています。

$ ls -l
合計 4
drwxr-xr-x 2 ubuntu ubuntu 4096  9月 16 18:01 TestDir
lrwxrwxrwx 1 ubuntu ubuntu    7  9月 16 17:53 TestDir-link -> TestDir

$ tree
.
├── TestDir
│   └── {TestDate1.txt}{TestDate2.txt}{TestDate3.txt}
└── TestDir-link -> TestDir

「やってしまいがちな危険なrmコマンド失敗事例」紹介

BAD:リンク元ディレクトリを指定してしまった

$ rm -rf TsetDir

リンク元ディレクトリとシンボリックリンクの名前が似ている場合に起きやすい「リンク元ディレクトリ」を指定したケースです。
当然のことながらディレクトリごと全て消えます。

絶望が訪れます。

BAD:削除したい、シンボリックリンク「TsetDir-link」の後に「/」をつけてパス指定してしまった

$ rm -rf TsetDir-link/

これが一番やってしまいがちな間違えやすい記述で、ディレクトリを指定する際つい「/」をつけてしまうとシンボリックリンクではなく
「シンボリックリンク先の配下」を指定したことになります。

この場合は、ディレクトリの中を再帰的に対象にし、
{TestDate1.txt}{TestDate2.txt}{TestDate3.txt} の全データは儚く消えます。

「あれシンボリックリンク消えないな~?」と、ディレクトリの中身を確認した段階で絶望が訪れます。

※そもそも rmコマンドで -f オプションは軽々しく使ってはいけない凶悪な危険物ですが、
慣れている環境だと"つい"無意識に使ってしまうケースもあるようなので気をつけたいところです。

unlink コマンドなら不発に終わり、事故が起きにくい

上記の危険なケースにおいて、unlinkコマンドならその仕様から不発に終わります。
試しに実行してみましょう。

$ unlink TsetDir
unlink: 'TsetDir' を削除 (unlink) できません: そのようなファイルやディレクトリはありません

これはディレクトリを削除できない仕様のため、リンク元ディレクトリを直接消すことはありません。

$ unlink TsetDir-link/
unlink: 'TsetDir-link/' を削除 (unlink) できません: そのようなファイルやディレクトリはありません

基本として直接的にファイル名を指定しないと消せない仕様のため、
ディレクトリ内を再帰的に処理できないので、ディレクトリの中身のファイル群を消すことはありません。

 

このように unlinkコマンドだと不発に終わる仕様のため、rmを使うことに比べてかなり事故リスクが減るわけですね。

まとめ:unlink コマンドがシンボリックリンクの削除に推奨される理由

rmコマンドでも、-i オプションをつけたり気をつければシンボリックリンクの削除に使用しても目的は果たせます。

ただし、人は失敗をする生き物で「それを無くすことは不可能です」
ならば事故を防止するため「そもそも人がミスできない、ミスしてもミスにならないようにする仕組み」が必要です。

この概念はフールプルーフと呼ばれる物で、これに基づいた運用として
作業をする際には、ミスが起きた時に影響が大きい rm より機能が限定されて影響が出にくいコマンドである unlink を使いましょうと言われる訳ですね。

という事で、本記事の解説は以上となります。
「unlink がなぜ推奨されるのか」を更に深掘りすると、「Linuxにおけるデータの構造」と「フールプルーフの大切さ」に触れることできます。

この記事をきっかけに、シンボリックリンク削除事故が減って貰えればになによりですし、Linuxの構造や安全性についても興味を持っていただければともおもいます。

ここまで読んでいただきまして、ありがとうございました!

参考資料

unlink(1) - Arch manual pages
https://man.archlinux.org/man/unlink.1.en

この記事がお役に立てば【 いいね 】のご協力をお願いいたします!
22
読み込み中...
22 票, 平均: 1.00 / 122
13,575
X facebook はてなブックマーク pocket
【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【2024.6.30 CentOS サポート終了】CentOS サーバー移行ソリューション

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【25卒向け】AI×バーチャル面接の募集を開始いたしました!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

【大阪 / 横浜】インフラエンジニア・サーバーサイドエンジニア 積極採用中!

この記事をかいた人

About the author

なか とも

2022年ビヨンドに中途入社
システムソリューション部所属
LPIC-3 304とAWS SAAを一応は持っています
普段の飲み物が牛乳とコーラと紅茶の3択しかない