2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

My Infrastructure JourneyAdvent Calendar 2024

Day 5

rmでシンボリックリンクを削除して事故った話

Last updated at Posted at 2024-12-04

はじめに

しばらく真面目な記事を書き続けていたので、閑話休題ということでこの記事では自分の仕事での失敗談を話していく。

筆者は新卒でインフラのバックグランド0の状態でやる気だけ持ってインフラ関係の部署に配属された人間である。この話はよくコマンドの内部構造を理解せず強い力を行使してしまったというものである。

事故の概要

下記のようなディレクトリ構成があってmodule1→module2にシンボリックリンクが貼られていた。(本来は同じディレクトリ名ではあるが説明用に名前を分けている)

infra-files/
  ├ project/
    └ module2
  └ module1

このような構成でmodule2のシンボリックリンクを削除したいとなったときに自分が打ったコマンドは、
rm -rf module2
確かにmodule2は抹消された。だがmodule1もこの時抹消されてしまったのだ。

rmとunlinkの違い

シンボリックリンクを削除するときよく言われるのはunlinkを使えというものだろう。
ではunlinkとrmの違いは何か、それは内部処理として再帰的にファイルを探索するかである。unlinkはシステムコールであり、rmはunlinkとrmdirを組み合わせていい感じにリッチにしたコマンドであったのだ。

それぞれのmamページを見ていこう。

このようにunlinkもrmの機能もファイルを削除するコマンドであることがわかる。
実際のコードの中身を見てみよう
https://github.com/coreutils/coreutils/blob/master/src/remove.c#L394
unlinkatはunlinkの上位互換コマンドであるため同様の中身であることがわかる。
コード内の以下の部分を見ると、rmはディレクトリツリーを構成して、そこを走査してファイルを削除していっていそうなことがわかる。

enum RM_status
rm (char *const *file, struct rm_options const *x)
{
  // ...
  FTS *fts = xfts_open (file, bit_flags, nullptr);

  while (true)
    {
      FTSENT *ent = fts_read (fts);
      // ...
      enum RM_status s = rm_fts (fts, ent, x);
      // ...
    }
}

まとめ

rmコマンドはなんでも消せる、実際消せた。
自分はそういう理解で生きてきたが、小さいものに大きすぎる力で挑むと誤って周りに被害を出してしまうかもしれない。
自分と同じことを起こす人が1人でも減るように祈っている。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?