パーミッションの基本
Linuxではすべてのファイルとディレクトリに「誰が何をできるか」を制御するアクセス権(パーミッション)が設定されています。
アクセス権は3種類の権限と3つのカテゴリの組み合わせで表現されます。
| 権限 | 記号 | 数値 | ファイルに対する意味 | ディレクトリに対する意味 |
|---|---|---|---|---|
| 読み取り | r | 4 | 内容を参照できる | ディレクトリ内の一覧を参照できる |
| 書き込み | w | 2 | 内容を変更できる | ファイルの新規作成・削除・名前変更ができる |
| 実行 | x | 1 | ファイルを実行できる | ディレクトリ内のファイルにアクセス・cdで移動できる |
この3つの権限を「所有者(user)」「グループ(group)」「その他ユーザ(other)」それぞれに設定します。
アクセス権の読み方
ls -l で表示されるパーミッション文字列を例に見てみます。
-rwxr-xr-- 1 user group 1234 Jan 9 12:00 script.sh
先頭の - はファイル種別(- は通常ファイル、d はディレクトリ、l はシンボリックリンク)です。続く9文字が3文字ずつ「所有者」「グループ」「その他」のパーミッションを表します。
この場合の数値表記への変換は以下のとおりです。
つまり rwxr-xr-- は数値表記で 754 となります。r=4, w=2, x=1 を足し算するだけなので、慣れれば一瞬で変換できます。
chmod ― アクセス権の変更
chmod(change mode)はファイルやディレクトリのパーミッションを変更するコマンドです。数値指定と記号指定の2通りの書き方があります。
# 数値指定
chmod 755 script.sh # rwxr-xr-x
# 記号指定
chmod u+x script.sh # 所有者に実行権を追加
chmod go-w config.txt # グループとその他から書き込み権を削除
chmod a+r readme.md # 全ユーザに読み取り権を追加
記号指定で使う対象・操作・権限の組み合わせは以下のとおりです。
| 対象 | 意味 | 操作 | 意味 | 権限 | 意味 |
|---|---|---|---|---|---|
| u | 所有者 | + | 追加 | r | 読み取り |
| g | グループ | – | 削除 | w | 書き込み |
| o | その他 | = | 設定 | x | 実行 |
| a | 全ユーザ | s | SUID/SGID | ||
| t | スティッキービット |
-R(--recursive)オプションを付けると、ディレクトリ以下のすべてのファイル・ディレクトリに再帰的に適用されます。
特殊パーミッション ― SUID・SGID・スティッキービット
通常のrwxに加えて、3つの特殊なパーミッションがあります。実務で遭遇する機会は限られますが、仕組みを知らないとセキュリティリスクを見逃すことになります。
SUID(Set User ID)
SUIDが設定されたファイルは、誰が実行しても「ファイル所有者の権限」で実行されます。代表例は /usr/bin/passwd です。一般ユーザが自分のパスワードを変更するとき、/etc/shadow への書き込みが必要ですが、SUIDによりroot権限で実行されるため変更が可能になっています。
chmod 4755 file # 数値指定(通常の755に4000を加算)
chmod u+s file # 記号指定
ls -l で確認すると、所有者の実行権が s になります(rwsr-xr-x)。
SGID(Set Group ID)
SGIDが設定されたファイルは「グループの権限」で実行されます。ディレクトリにSGIDを設定した場合、そのディレクトリ内に作成される新しいファイルは親ディレクトリのグループを自動的に継承します。チーム共有ディレクトリで便利です。
chmod 2755 dir # 数値指定(2000を加算)
chmod g+s dir # 記号指定
スティッキービット
ディレクトリにスティッキービットを設定すると、そのディレクトリ内のファイルは所有者本人(とroot)しか削除できなくなります。/tmp ディレクトリに設定されているのが典型例です。全ユーザが書き込めるが、他人のファイルは消せない、という状態を実現します。
chmod 1777 /tmp # 数値指定(1000を加算)
chmod o+t /tmp # 記号指定
ls -l で確認すると、その他ユーザの実行権が t になります(rwxrwxrwt)。
特殊パーミッションは便利な反面、不要なSUIDが残っているとセキュリティホールになります。定期的に find / -perm -4000 でSUID付きファイルを洗い出す運用が推奨されます。
umask ― デフォルトパーミッションの制御
ファイルやディレクトリを新規作成したとき、パーミッションは自動で設定されます。その初期値を決めるのが umask です。
計算式はシンプルな引き算です。
- ファイル:
666 - umask値 - ディレクトリ:
777 - umask値
例えば umask 022 の場合、新規ファイルは 644(rw-r–r–)、新規ディレクトリは 755(rwxr-xr-x)になります。
umask # 現在の値を確認
umask 027 # 値を変更(その他ユーザのアクセスをすべて禁止)
サーバ構築時やデプロイスクリプトで意図しないパーミッションのファイルが作られる場合、umaskの設定が原因であることが多いです。
chown / chgrp ― 所有者・グループの変更
# 所有者を変更
chown nginx /var/www/html/index.html
# 所有者とグループを同時に変更
chown nginx:www-data /var/www/html/
# グループのみ変更
chown :www-data /var/www/html/
# または
chgrp www-data /var/www/html/
# 再帰的に変更
chown -R nginx:www-data /var/www/html/
Webサーバのドキュメントルートやアプリケーションのログディレクトリなど、適切な所有者・グループを設定しないとプロセスがファイルを読み書きできずエラーになります。トラブルシュートで最初に確認すべきポイントの一つです。
ファイル操作の基本コマンド
日常的に使うファイル操作コマンドをまとめます。
ls ― ファイル一覧の表示
ls -l # 詳細表示(パーミッション、所有者、サイズ、更新日時)
ls -la # 隠しファイルも含めて詳細表示
ls -lh # サイズをKB/MB単位で表示
ls -li # iノード番号を表示
ls -lR # サブディレクトリの内容も再帰的に表示
ls -d */ # ディレクトリのみ表示
cp ― コピー
cp file1.txt file2.txt # ファイルコピー
cp -r dir1/ dir2/ # ディレクトリを再帰的にコピー
cp -p file.txt backup/ # 属性(パーミッション・タイムスタンプ)を保持してコピー
cp -i file.txt dest/ # 上書き前に確認
cp -f file.txt dest/ # 強制上書き(既存ファイルを削除してコピー)
mv ― 移動・リネーム
mv old.txt new.txt # リネーム
mv file.txt /tmp/ # 移動
mv -i file.txt dest/ # 上書き前に確認
mv -f file.txt dest/ # 強制上書き
rm ― 削除
rm file.txt # ファイル削除
rm -i file.txt # 削除前に確認
rm -r dir/ # ディレクトリを再帰的に削除
rm -rf dir/ # 確認なしで再帰的に削除(要注意)
rm -rf / は冗談でも実行してはいけません。最近のディストリビューションでは --no-preserve-root を付けないと実行できない安全策がありますが、対象パスを変数で渡すスクリプトでの事故は今でも起こります。
mkdir ― ディレクトリ作成
mkdir newdir # 作成
mkdir -p parent/child/grandchild # 親ディレクトリも含めて一気に作成
mkdir -m 700 secret # パーミッションを指定して作成
rmdir ― 空ディレクトリの削除
rmdir emptydir # 空のディレクトリのみ削除可能
rmdir -p a/b/c # 階層ごとまとめて削除(すべて空の場合のみ)
中身があるディレクトリを削除するには rm -r を使います。
touch ― タイムスタンプ更新・空ファイル作成
touch newfile.txt # ファイルが存在しなければ空ファイルを作成
touch existing.txt # 既存ファイルのタイムスタンプを現在時刻に更新
touch -t 202401091200 file.txt # 指定した日時(2024/01/09 12:00)に変更
touch -a file.txt # アクセス時刻のみ変更
touch -m file.txt # 修正時刻のみ変更
dd ― ブロック単位のファイル作成・コピー
# 1MBのテストファイルを作成
dd if=/dev/zero of=testfile bs=1M count=1
# ディスクイメージの作成
dd if=/dev/sda of=disk.img bs=4M
# ISOイメージをUSBに書き込む
dd if=ubuntu.iso of=/dev/sdb bs=4M status=progress
if が入力元、of が出力先、bs がブロックサイズ、count がコピー回数です。ディスクのクローンやブータブルUSBの作成でよく使われます。
ハードリンクとシンボリックリンク
Linuxのファイルシステムには2種類のリンクがあります。違いを正確に理解していないとトラブルの原因になります。
両者の特性を表にまとめます。
| ハードリンク | シンボリックリンク | |
|---|---|---|
| iノード | 元ファイルと同一 | 別のiノードを持つ |
| 元ファイル削除時 | 他のリンクが残っていれば実体は消えない | リンク切れになる |
| 別ファイルシステム | 作成不可 | 作成可 |
| ディレクトリ | 作成不可 | 作成可 |
ls -l 表示 | 通常のファイルと同じ | 先頭に l が表示される |
# ハードリンクの作成
ln original.txt hardlink.txt
# シンボリックリンクの作成
ln -s /var/log/syslog ~/syslog_link
実務ではシンボリックリンクを使う場面が圧倒的に多いです。設定ファイルの切り替え(/etc/nginx/sites-enabled/ にシンボリックリンクを張る等)やバージョン管理(/opt/app/current → /opt/app/v2.1.0)は定番パターンです。
圧縮・アーカイブ
圧縮コマンド ― gzip / bzip2 / xz
3つのコマンドは圧縮率と速度のトレードオフが異なりますが、オプション体系はほぼ共通です。
| コマンド | 拡張子 | 圧縮率 | 速度 | 展開コマンド |
|---|---|---|---|---|
| gzip | .gz | 低 | 高速 | gunzip / gzip -d |
| bzip2 | .bz2 | 中 | 中間 | bunzip2 / bzip2 -d |
| xz | .xz | 高 | 低速 | unxz / xz -d |
共通する主要オプションは以下のとおりです。
| オプション | 意味 |
|---|---|
| -d | 展開 |
| -k | 元ファイルを残す(gzip/bzip2/xzすべて共通) |
| -c | 標準出力に出力 |
gzip file.txt # file.txt.gz が作られ、元ファイルは消える
gzip -k file.txt # 元ファイルを残す
gzip -d file.txt.gz # 展開
デフォルトでは元ファイルが削除される点に注意してください。元ファイルを残したい場合は -k を忘れずに付けます。
tar ― アーカイブ
tar(tape archive)は複数のファイルを1つにまとめるコマンドです。圧縮コマンドと組み合わせて使うのが一般的です。
# gzip圧縮でアーカイブ作成
tar czf archive.tar.gz dir/
# bzip2圧縮でアーカイブ作成
tar cjf archive.tar.bz2 dir/
# xz圧縮でアーカイブ作成
tar cJf archive.tar.xz dir/
# アーカイブの展開
tar xzf archive.tar.gz
# 内容の一覧表示(展開せずに確認)
tar tzf archive.tar.gz
オプションの覚え方として、c(create)/ x(extract)/ t(list)が操作、z(gzip)/ j(bzip2)/ J(xz)が圧縮方式、f(file)がファイル名指定、v(verbose)が詳細表示です。f は必ず最後に置き、直後にファイル名を指定します。
FHS ― ディレクトリ構造の標準
FHS(Filesystem Hierarchy Standard)はLinuxのディレクトリレイアウトの標準仕様です。どのディストリビューションでも基本構造は共通なので、これを知っていれば「設定ファイルはどこ?」「ログはどこ?」で迷うことがなくなります。
実務で頻繁にアクセスするディレクトリを中心に整理します。
| ディレクトリ | 用途 |
|---|---|
/bin | システム起動・修復に必要な基本コマンド |
/sbin | システム管理用コマンド(一般ユーザは通常使わない) |
/etc | システム全体の設定ファイル |
/home | 一般ユーザのホームディレクトリ |
/root | rootユーザのホームディレクトリ |
/var | ログ・キャッシュ・スプールなど可変データ |
/var/log | 各種ログファイル |
/tmp | 一時ファイル(再起動時に削除される可能性あり) |
/usr | ユーザ向けプログラム・ライブラリ(読み込み専用) |
/usr/bin | 一般ユーザ向けコマンド |
/usr/local | ローカルにインストールしたソフトウェア |
/opt | アドオンパッケージ |
/dev | デバイスファイル |
/proc | カーネル・プロセス情報(疑似ファイルシステム) |
/boot | ブートローダ関連ファイル |
/lib | 共有ライブラリ |
/media | リムーバブルメディアのマウントポイント |
/mnt | 一時マウント用 |
トラブルシュートの場面では、この知識が直接役立ちます。「Nginxの設定を変えたい」→ /etc/nginx/、「アプリのログを見たい」→ /var/log/、「ディスクが溢れた」→ /var と /tmp を最初に確認、といった具合です。
ファイル検索コマンド
find ― 条件指定で検索
find はディレクトリツリーを再帰的に辿り、条件に合うファイルをリアルタイムに検索します。
# /var/log以下で.logファイルを検索
find /var/log -name "*.log"
# 7日以内に更新されたファイル
find /home -mtime -7
# サイズが100MB以上のファイル
find / -size +100M
# SUID付きファイルを検索
find / -perm -4000
# 検索結果に対してコマンドを実行
find /tmp -name "*.tmp" -exec rm {} \;
locate ― データベースで高速検索
locate はあらかじめ構築されたデータベースを使うため、find より高速です。ただしデータベースが古いと最新のファイルは見つかりません。
locate nginx.conf # ファイル名で検索
sudo updatedb # データベースを手動更新
データベースは通常 cron で定期更新されますが、作成直後のファイルを検索したい場合は先に updatedb を実行する必要があります。
which / whereis / type ― コマンドの所在確認
which python3 # PATHから実行ファイルの場所を表示
whereis nginx # バイナリ・ソース・マニュアルの場所を表示
type ls # コマンドの種類(ビルトイン/外部/エイリアス)を表示
which は「今実行されるのはどのバイナリか」を確認するときに使います。Pythonやnodeなど複数バージョンが混在する環境で、意図したバイナリが使われているか確認する場面は多いです。
実践のヒント
パーミッション関連のトラブルは「Permission denied」というエラーメッセージで表面化しますが、原因はさまざまです。切り分けの手順として、まず ls -la で対象ファイルの所有者・パーミッションを確認し、次にプロセスがどのユーザで動いているかを ps aux | grep プロセス名 で確認します。この2つを突き合わせれば、chmodで権限を変えるべきかchownで所有者を変えるべきかが判断できます。
圧縮コマンドは「gzipで大体OK、サイズを極限まで絞りたいときだけxz」と覚えておけば実務では困りません。tarのオプションは czf(作成)と xzf(展開)の2パターンを手が覚えるまで繰り返し使うのが最短ルートです。
FHSのディレクトリ構造は丸暗記しようとせず、man hier コマンドでいつでも参照できることを覚えておいてください。