Linuxで所有者と権限を指定してディレクトリを作成する(install -d)

Linux で作業していると、ディレクトリを作ってから所有者と権限を直す、という手順を何度も踏むことになります。

$ mkdir /var/www/app
$ chown appuser:appuser /var/www/app
$ chmod 755 /var/www/app

3回に分けるのが地味に面倒です。install -d を使うと、これを1回で済ませられます。

$ install -d -m 0755 -o appuser -g appuser /var/www/app

なぜ面倒なのか

Web アプリケーションを /var/www/app に置く、といった配置をよくします。このとき所有者は一段ごとに違うことが多いはずです。

  • /var/www は root のまま
  • /var/www/app はアプリケーションの実行ユーザー(nginx や専用ユーザー)

この「親は root、その下だけ別ユーザー」という形を作るのが、mkdir と chown の組み合わせだと少し気を使います。mkdir -p で一気に作ってから chown -R をかけると、変えたくない親まで巻き込むからです。

install -d は最終ディレクトリだけに適用される

install -d の便利なところは、途中のディレクトリは既定のまま作り、指定した所有者と権限は最後のディレクトリにだけ適用する点です。

$ install -d -m 0755 -o appuser -g appuser /var/www/app

結果を確認すると、こうなります。

パス所有者権限
/varroot:root755
/var/wwwroot:root755
/var/www/appappuser:appuser755

まさに冒頭で挙げた「親は root、その下だけアプリユーザー」がそのまま出来上がります。mkdir -p 相当の働きをしつつ、所有者の適用範囲は最後だけ、というのがちょうどよく効きます。

オプションはそれぞれ次の意味です。

  • -d — ディレクトリを作成する(親が無ければまとめて作る)
  • -m — 権限(chmod 相当)
  • -o — 所有者(chown 相当)
  • -g — グループ

chown -R だと親まで巻き込む

比較のために、mkdir -p してから chown -R をかけた場合を見てみます。

$ mkdir -p /var/www/app
$ chown -R appuser:appuser /var/www
パス所有者権限
/var/wwwappuser:appuser755
/var/www/appappuser:appuser755

/var/www の所有者まで変わってしまいました。-R を付けた以上は当然の結果ですが、ここを root のままにしておきたい場面は多いはずです。かといって chown を階層ごとに打ち分けるのも面倒で、結局そこが install -d の出番になります。

既存のディレクトリにも使える

install -d は、対象がすでに存在していてもエラーにならず、所有者と権限を指定どおりに直してくれます。

# 実行前: root:root 700
$ install -d -m 0755 -o appuser -g appuser /srv/app
# 実行後: appuser:appuser 755

終了コードは 0 です。「無ければ作る、あれば整える」という動きなので、セットアップ用のスクリプトに置いておくと何度流しても同じ状態に落ち着きます。Ansible の file モジュールを手で書いているような感覚に近いです。

一方で、既存ディレクトリの中身には影響しません。

$ install -d -m 0755 /srv/app

これを実行しても、/srv/app の中にあるファイルやサブディレクトリの権限はそのままです。chmod -R のつもりで使うと目的を果たせないので、そこは区別してください。逆に言えば、うっかり中身を書き換えてしまう心配もありません。

umask の影響を受けない

-m を省略した場合、install -d は umask に関係なく 755 で作成します。mkdir と挙動が違う点です。

umaskinstall -dmkdir
022755755
077755700
000755777

umask を絞った環境で mkdir と同じつもりで使うと、意図より緩い権限になります。権限を明示したいなら -m は常に書くのが安全です。

グループで共有したいときは setgid

アプリユーザーが書き込み、nginx が読む、といった共有をしたい場合は setgid(2 始まりのモード)を付けておくと、あとから中に作られるファイルがディレクトリのグループを引き継ぎます。

$ install -d -m 2775 -o appuser -g www-data /var/www/app

このディレクトリの中にファイルを作ると、作成者が誰であってもグループは www-data になります。デプロイのたびにグループを直して回る手間が減ります。

Dockerfile や Ansible での書き方

Dockerfile では RUN に一行書くだけで、レイヤーを増やさずに済みます。

RUN install -d -m 0755 -o appuser -g appuser /var/www/app

指定するユーザーとグループがその時点で存在している必要があるので、useradd の後に置いてください。なお BusyBox の install でも同じ挙動なので、Alpine ベースのイメージでもそのまま使えます。

Ansible を使っているなら、素直に file モジュールを使うほうが読みやすいです。

- name: アプリケーションのディレクトリを作成する
  ansible.builtin.file:
    path: /var/www/app
    state: directory
    owner: appuser
    group: appuser
    mode: "0755"

install -d の出番は、シェルスクリプトや Dockerfile、あるいは手作業で ssh に入っているときです。

まとめ

  • install -d -m MODE -o USER -g GROUP PATH で、作成・所有者・権限を1回で指定できる
  • 途中のディレクトリは既定のまま作られるので、/var/www は root、/var/www/app だけアプリユーザー、という形がそのまま作れる
  • 既存ディレクトリにも使えるが、中身には影響しない
  • -m を省略すると umask に関係なく 755 になる

地味に便利です。

コメントを書く

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。

Shares