[Linux] 削除できないファイルの作り方 | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

サーバーを管理していると、削除や変更されたくないファイルやディレクトリというものが出てきたりします。

権限や所有者を適切にコントロールすることでそれらを対応させることもできますが、Linuxの場合はrootユーザーは何でもありの特権を持っていますし、優れたユーザー管理の機構がLinuxには存在するわけでもないため、管理が煩雑になったり、それだけではうまくコントロールしきれないケースも出てきたりします。


ここで紹介する、Linux上の特殊な権限を操作するchattrコマンドを使えば、削除や変更ができないファイルや追記のみ許可するファイルなどを作り出すことができます。

なお、chattrコマンドはext2またはext3のファイルシステム上での属性変更を可能とするものです。



ファイル・ディレクトリを削除できないように権限を変更する


まずは、削除できないファイルにするために、権限を変更してみましょう。


# touch foo.txt

# chattr +i foo.txt

# rm foo.txt
rm: remove write-protected 通常の空ファイル `foo.txt'? y
rm: cannot remove `foo.txt': 許可されていない操作です

# echo "xyz" >> foo.txt
-bash: foo.txt: 許可がありません


chattrコマンドに「+i」オプションをつけることで、削除・変更ができないファイルとなります。

ちなみにファイル名の変更もできなくなります。


そして、上記の操作を見てもらえればわかるとおり、rootユーザーでさえファイルの削除が行えなくなります。

なお、この権限を削除したい場合は「-i」オプションをつけて実行します。


# chattr -i foo.txt

# rm foo.txt
rm: remove write-protected 通常の空ファイル `foo.txt'? y
(削除される)


ディレクトリの場合も、操作は同様です。


# mkdir hoge_dir

# chattr +i hoge_dir/

# rmdir hoge_dir/
rmdir: `hoge_dir/': 許可されていない操作です


追記モードでしか開けないファイルを作る


ファイルを「追記モード」でしか開くことができず、また削除もできないファイルを作ってみます。


用途としては、例えばログファイルを作る場合に有効になるのではないでしょうか。

時に重要な意味を持つログファイルは、運用の中で削除されてしまっては困ります。

ただ、変更もできないとなるとログファイルへの書き込みができません。

追加で書き込むのは許可しつつも、ファイルの削除はされたくないという場合に、この権限設定が活きてきます。


# cat foo.txt
abc

# chattr +a foo.txt

# echo "xyz" > foo.txt
-bash: foo.txt: 許可されていない操作です

# echo "xyz" >> foo.txt

# cat foo.txt
abc
xyz

# rm foo.txt
rm: remove 通常ファイル `foo.txt'? y
rm: cannot remove `foo.txt': 許可されていない操作です

# chattr -a foo.txt

# rm foo.txt
rm: remove 通常ファイル `foo.txt'? y
(削除される)


追記モードでしかファイルを開かせないためのオプションは「+a」オプションです。

途中でfoo.txtファイルに2つの操作をしています。


# echo "xyz" > foo.txt

ファイルに文字を書き込んで上書きしようとしています。

この操作は、はじかれています。


一方で、ファイルの末尾に追加するリダイレクトの操作は問題なく動作しています。


# echo "xyz" >> foo.txt

また、このオプションを付けることでファイルの削除もできなくなっています。

この特殊な権限を取り除きたい場合は、「-a」オプションをつけて実行します。



特殊な権限を見るためのlsattrコマンド


この特殊な権限は、lsコマンドで見てもどこにも表されていません。


# ls -la
合計 12
drwxr-xr-x 3 root root 4096 11月 18 10:34 .
drwx------ 10 root root 4096 11月 18 10:23 ..
-rw-r--r-- 1 root root 0 11月 18 10:33 foo.txt
drwxr-xr-x 2 root root 4096 11月 18 10:34 hoge_dir

この権限を見る場合は、「lsattr」コマンドを利用します。


# lsattr
-----a------- ./foo.txt
----i-------- ./hoge_dir

上記の場合、foo.txtにaオプション(ファイルへの追記のみ許可)、hoge_dirディレクトリにiオプション(ファイルの削除・変更不可)がセットされていることがわかります。



プログラムからの操作はどうだ?


最後に、プログラムからこの特殊な権限を付け加えたファイルを操作して動作を検証してみます。


# lsattr
-----i------- ./foo.txt

この状態のファイルに対して、PHPのプログラムから操作してみます。

プログラム自体はこんな感じに。


- file.php
<?php

$fp = fopen("./foo.txt", "r");

while (!feof($fp)) {
$buff = fgets($fp, 1024);
echo $buff;
}

fclose($fp);

まずは、読み取りから


# cat foo.txt
abc

# php file.php
abc

これは、問題なく動作します。


次に、書き込みを行ってみます。

最初のfopen時に書き出しのみのモードでファイルを開いてみます。


$fp = fopen("./foo.txt", "w");

上記の編集を加えて実行してみると・・・。


# php file.php
PHP Warning: fopen(./foo.txt): failed to open stream: Permission denied in /home/hoge/sc/file.php on line 3

権限がないというエラーメッセージが出ました。

これは、追記モードで開いても同様の結果です。


次に、foo.txtを追記モードで開けるように変更してみます。


# chattr +a foo.txt

# lsattr
-----a------- ./foo.txt

この状態で、先ほどのPHPスクリプトを書き出しモード(wオプション)でファイルを開いてみます。


# php file.php
PHP Warning: fopen(./foo.txt): failed to open stream: Operation not permitted in /home/hoge/sc/file.php on line 3

今度は、操作が許可されていないというエラーメッセーが出ています。


では、操作が許可されている追記モードで開いてみます。


$fp = fopen("./foo.txt", "a");

上記の編集を加えて実行してみると・・・。


# php file.php
abc

こちらは、ちゃんと操作ができました。

じゃあ、実際に追記モードでファイルに書き込んでみます。

スクリプトを変更してこんな感じに。


<?php

$fp = fopen("./foo.txt", "a");
fwrite($fp, "xyz");
fclose($fp);

$fp = fopen("./foo.txt", "r");

while (!feof($fp)) {
$buff = fgets($fp, 1024);
echo $buff;
}

fclose($fp);

上記のPHPスクリプトを実行させてみると・・・。


# php file.php
abc
xyz

ちゃんと書き込んでいますね。


用途は限定的であるものの、サーバー管理をしていく中で覚えておくと便利なコマンドではないでしょうか。