読者です 読者をやめる 読者になる 読者になる

すこしふしぎ.

VR/HI系院生による技術ブログ.まったりいきましょ.(友人ズとブログリレー中.さぼったら焼肉おごらなきゃいけない)

【vagrant】共有フォルダのパーミッションで悩んだ話【chmodできない】

こんばんは.1000chです. 最近なにかと話を聞くvagrant.みなさん使っていますでしょうか. 自分は今,バイト先のチーム開発で利用しています. vagrantファイルが置いてあるディレクトリのフォルダはゲストマシンとホストマシンでの共有フォルダとして利用でき, ホスト側から普段の開発環境でコーディング,ゲスト側でサーバ起動,なんてことができてなかなか快適です.

しかし今回,共有フォルダを利用しているが故の穴にはまってしまいましたので備忘録としてメモを残しておきます.

今回起こった現象

今回起こったのは,共有フォルダにおけるchmodの挙動に関する問題です.

まずはこちらのコードをご覧ください.

<?php
      // 中略
      if( !file_exists($upload_dir)){
        umask(0000);
        mkdir($upload_dir,0777);
        chmod($upload_dir,0777);
      }

      move_uploaded_file($tmp_name, $save_path);

なんてこたない,phpにおけるファイルアップロードのコードです.

  • アップロードするためのディレクトリがないとき
  • アップロード先ディレクトリにファイルを保存

という流れですね.ところが,これがなかなかに問題となってしまうのです.

ファイルアップロードできない...

普通にうごくだろー,と思って動かしてみるも,なぜかmove_upload_fileでフォルダのパーミッションエラーが発生してしまいます.

実際にディレクトリを見てみると,$upload_dirのディレクトリは生成されているものの,ls -lするとパーミッションが755のままになっていました.

...どういうことだろう?

mkdirはうごいているが,chmodが無効なのだろうか?

ということで

<?php
//中略
      if( !file_exists($upload_dir)){
        umask(0000);
        mkdir($upload_dir,0777);
        echo chmod($upload_dir,0777) ? "success" : "fail";
      }

      move_uploaded_file($tmp_name, $save_path);

と書き換えてみます.

...なんと,"success"も"fail"もどちらも出力されない.いよいよ訳が分からないので,chmodのコードだけを作って動かしてみます.

<?php
//chmod_test.php
chmod("./chmod_test",0777);
?>
$ mkdir chmod_test
$ php chmod_test.php
..
drwxr-xr-x   1 vagrant vagrant    68  45 22:58 2014 chmod_test
..

おいおい...phpからのchmodが全然呼ばれていないではないか..

コンソールからchmodしてみる

ならば,ということで,ターミナルから直接chmodしてみる.

$ chmod 777 chmod_test
$ ls -l
..
drwxr-xr-x   1 vagrant vagrant    68  45 22:58 2014 chmod_test
..

おいおいおいおい!そもそもchmodできないではないか!

あかんこれ詰まった...

他人の環境で試してみる

さすがに何かがおかしい.と思い別の人の環境で同じことをしてみると...

普通にchmodできるじゃないか!!!

そこで気づく.共有フォルダがいけないのではないかと...

まぁたしかに,ゲストマシンからホストマシンのパーミッションを変えられたらちょっとアレだなとは思いますね.

そっかー,共有フォルダではchmod使えないのかー,残念.まぁ本番環境では動きそうだから我慢するかー,と一旦あきらめることに.

vagrantfileの設定を見直す

そんな中,別件で調査中にstackoverflowでこんなの 見つけました.抜粋すると

config.vm.share_folder "v-data", "/export", "/export", :owner=> 'vagrant', :group=>'httpd', :mount_options => ['dmode=775', 'fmode=775']

この:mount_optionってやつ怪しくないか?

ということで,vagrantの公式を参考にしつつ,vagrantfileに以下の記述を追加.

 config.vm.synced_folder ".", "/vagrant", mount_options: ['dmode=777','fmode=755']

この状態で改めてVMを再起動.すると...

[host ]$ vagrant up
[host ]$ vagrant ssh
[guest]$ cd /vagrant
[guest]$ ls -al
..
drwxrwxrwx   1 vagrant vagrant    68  45 22:58 2014 chmod_test
..

ディレクトリのパーミッションが変更されている!やった!

この状態で冒頭のコードを動かすと,きちんとmkdirされたディレクトリのパーミッションも777にでき,無事ファイルのアップロードができました!

どうやらdmodeがディレクトリパーミッションfmodeがファイルのパーミションのようです.

感想

なんとなく使えるからいっかー,と思ってましたが,仮想マシンでの開発に慣れたこのごろ,そろそろvagrantfileの他の設定や,chef / puppetを使ったサーバ設定の書き方とかも勉強しなきゃなぁと思いましたとさ.

まとめ

vagrantの共有フォルダでパーミッションを指定するには

 config.vm.synced_folder "</path/to/_dir>", "</path/on/guest>", mount_options: ['dmode=<dir_permission>','fmode=<file_permission>']