18
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Linux】変な パーミッション【Ansible】

Last updated at Posted at 2025-07-07

要約

  • YAMLで8進数を書くときは、クォーテーションをしよう!
  • クォーテーションしないと、こういう意味のわからんパーミッションが急に出てきて、死ぬぞ
user@deskmeetserver:/tmp$ ls -ld test_dir/
d-wxrw--wt 2 user user 4096 May 17 09:41 test_dir/

経緯

登場人物 ・インフラ園児 ニアちゃん
 ・Linuxを中心に触っているインフラエンジニア。
  3歳児だと自分のことを思い込んでいる。
・現場のおねえさん
 ・現場のおねえさん。やさしい。
※パーミッションが変だったのはホントですが、ほかは全部フィクションです。フィクションなんだってば。

ある日の昼下がりのこと。
おねえさん「あのー……」
ニアちゃん「なぁに?」
おねえさん「ニアちゃんが作ったこのディレクトリ、パーミッションおかしくない…………?」

user@deskmeetserver:/tmp$ ls -ld test_dir/
d-wxrw--wt 2 user user 4096 May 17 09:41 test_dir/

ニアちゃん「なにこれ」

おかしいですね。奇っ怪なパーミッションです。
数字にすると1363でしょうか。

いくら経験の浅いニアちゃんといえど、chmod 1363なんて打ったら違和感を感じるはずです。

こんな変なパーミッション、設定したらどうなるんでしょうか?ちょっと見てみましょうか。

ニアちゃん「中のファイルとかもどうなってるんだろう、これ」
ニアちゃん「lsでディレクトリの中身を見ることは…できないね」
おねえさん「ユーザに読み取り権限がないものね」
ニアちゃん「だけどグループには読み取り権限があるから、見られそうな気もするけど」
おねえさん「所有ユーザの場合は、そもそもグループの読み取り権限を参照しないのね。普通ユーザのほうが狭いパーミッションなんてつけないから、おねえさんも知らなかったな」

user@deskmeetserver:/tmp$ ls -la test_dir/
ls: cannot open directory 'test_dir/': Permission denied

ニアちゃん「あっ、中には入れるんだね」
おねえさん「実行権限があるからね」
ニアちゃん「でも読み取り権限はないから、cdしたあとでもやっぱりファイルの一覧は見れないんだね」

user@deskmeetserver:~$ cd test_dir/

user@deskmeetserver:~/test_dir$ ls -la
ls: cannot open directory '.': Permission denied

ニアちゃん「ディレクトリ内にファイルの作成・削除は…できる。書き込み権限はあるからね」
おねえさん「あの、ちょっと勝手に変なファイル作らないで……」

user@deskmeetserver:~/test_dir$ echo hoge > hoge

user@deskmeetserver:~/test_dir$ ls -l hoge
-rw-rw-r-- 1 user user 5 May 17 10:52 hoge

user@deskmeetserver:~/test_dir$ cat hoge
hoge

user@deskmeetserver:~/test_dir$ rm hoge

user@deskmeetserver:~/test_dir$ ls -l hoge
ls: cannot access 'hoge': No such file or directory

ニアちゃん「中にいるファイルは…見れないけど、書き込めるんだね」
おねえさん「ファイルにも書き込み権限がついているみたい」

user@deskmeetserver:~/test_dir$ ll test.txt
--w----r-T 1 user user 21 Jul  7 12:27 test.txt
user@deskmeetserver:~/test_dir$ cat test.txt
cat: test.txt: Permission denied

user@deskmeetserver:~/test_dir$ sudo cat test.txt
test file

user@deskmeetserver:~/test_dir$ cat test.txt
cat: test.txt: Permission denied

user@deskmeetserver:~/test_dir$ sudo cat test.txt
test file
write test

ニアちゃん「削除もできる」
ニアちゃん「ファイルの削除は、ディレクトリの書き込み権限に依存するからね」
おねえさん「あの……勝手にいじらないで……」

user@deskmeetserver:~/test_dir$ rm test.txt

user@deskmeetserver:~/test_dir$ ll test.txt
ls: cannot access 'test.txt': No such file or directory

閑話休題。

解説

問題を起こしたのは、ざっくり下記みたいなPlaybookでした。
(記憶をもとに雑に再現しています)

- hosts: servers
  tasks:
    - name: directory creation
      file:
        path: /tmp/test_dir
        state: directory
        owner: user
        group: user
        mode: 755
    - name: copy test1
      copy:
        src: test.txt
        dest: /tmp/test_dir/test.txt
        owner: user
        group: user
        mode: 644
    - name: copy test2
      copy:
        src: test.txt
        dest: /tmp/test_dir/test2.txt
        owner: user
        group: user
        mode: 600

まずいのはmode: 755の部分。
YAMLの仕様で、0始まりでなくクオートされていない数字は、10進数として解釈されてしまうようです。
そしてこの現象が起こると、かなりの確率で、ユーザに読み取りを許可していない謎のパーミッション状態が誕生します……
755(10進数)=1363(8進数) d-wxrw--wt
644(10進数)=1204(8進数) --w----r-t
600(10進数)=1130(8進数) ---x-wx--t

ひどい罠かと思いきゃ、公式ドキュメントにも、この仕様はちゃんと載っています。

For consistent results, quote octal numbers (for example, '644' or '1777') so Ansible receives a string and can do its own conversion from string into number. Adding a leading zero (for example, 0755) works sometimes, but can fail in loops and some other circumstances.
Giving Ansible a number without following either of these rules will end up with a decimal number which will have unexpected results.

(参考訳)
意図した通りの結果を得るためには、8進数はクォートされなくてはなりません('644'や'1777'のように)。これにより、Ansibleは値を文字列として受け取り、Ansible自身で(8進数として)変換されます。
先頭にゼロを付与する方法(0755のように)は、ときに機能しますが、ループやその他の状況下では失敗する可能性があります。
これらのいずれの方法にもよらずに、Ansibleに数値を与えた場合、10進数として解釈され、意図しない結果をもたらします。

修正

上記に則って修正すると……

- hosts: servers
  tasks:
    - name: directory creation
      file:
        path: /home/user/test_dir
        state: directory
        owner: user
        group: user
        mode: '0755'
    - name: copy test1
      copy:
        src: test.txt
        dest: /home/user/test_dir/test.txt
        owner: user
        group: user
        mode: '0644'
    - name: copy test2
      copy:
        src: test.txt
        dest: /home/user/test_dir/test2.txt
        owner: user
        group: user
        mode: '0600'
user@deskmeetserver:~$ ls -ld test_dir/
drwxr-xr-x 2 user user 4096 Jul  7 12:39 test_dir

user@deskmeetserver:~$ ls -l test_dir/
total 8
-rw------- 1 user user 10 Jul  7 12:39 test2.txt
-rw-r--r-- 1 user user 10 Jul  7 12:39 test.txt

想定通りのパーミッションでファイルを作ることができました!

まとめ

  • YAMLに10進数以外の数字を渡すときには、クォーテーションが必要
    • この問題を踏みやすいものの一つに、ファイルパーミッションの指定がある
  • 騒ぐ前にドキュメントを読もう(自戒)
18
1
1

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
18
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?