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

風柳メモ

ソフトウェア・プログラミング関連の覚書が中心。

mountしたWindows7上のPHPファイルが実行できない?

Linux (CentOS 6.6) で、Windows 7 上のフォルダを mount したとき、Linux 上からそのフォルダ下にある PHP ファイルを実行しようとすると、エラーになってしまう……。
同じフォルダに置いた Python や Ruby 等のスクリプトについては、問題なく実行できる。


今のところ原因が全くわからないので、ご存じの方は教えてほしい。



解決編

改めて検索してみたら、解決策があった。

Add 'noserverino' option, and the problem is settled.

windows - PHP crazy behavior on mount - Super User
[user@linuxhost ~]$ sudo mount -t cifs "//win7host/src" /mnt/src -o username=user,password=pass,uid=500,gid=500,file_mode=0755,dir_mode=0755,noserverino

This doesn't sound like a PHP problem at all. My best guess is that you have a 32/64-bit mismatch here. And PHP doesn't currently support 64-bit inodes.

PHP :: Bug #50150 :: stat() / lstat() does not work on a mounted cifs

使用しているPHPのバージョンが64ビット inode をサポートしていないので、ホスト側(Windows側)が64ビット版の場合にこの問題が起こるらしい。

Inode Numbers

When Unix Extensions are enabled, we use the actual inode number provided by the server in response to the POSIX calls as an inode number.

When Unix Extensions are disabled and "serverino" mount option is enabled there is no way to get the server inode number. The client typically maps the server-assigned "UniqueID" onto an inode number.

Note that the UniqueID is a different value from the server inode number. The UniqueID value is unique over the scope of the entire server and is often greater than 2 power 32. This value often makes programs that are not compiled with LFS (Large File Support), to trigger a glibc EOVERFLOW error as this won't fit in the target structure field. It is strongly recommended to compile your programs with LFS support (i.e. with -D_FILE_OFFSET_BITS=64) to prevent this problem. You can also use "noserverino" mount option to generate inode numbers smaller than 2 power 32 on the client. But you may not be able to detect hardlinks properly.

mount.cifs(8) - Linux man page


なお、64ビット環境のLinuxからmountした場合には、noserverino オプションをつけなくても動作した。



環境

[user@linuxhost ~]$ # === OS バージョン確認
[user@linuxhost ~]$ uname -a
Linux linuxhost.localdomain 2.6.32-504.el6.i686 #1 SMP Wed Oct 15 03:02:07 UTC 2014 i686 i686 i386 GNU/Linux
[user@linuxhost ~]$ cat /etc/redhat-release
CentOS release 6.6 (Final)
[user@linuxhost ~]$ # === PHP バージョン確認
[user@linuxhost ~]$ php -v
PHP 5.4.28 (cli) (built: May  2 2014 18:40:44)
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies

不具合発生手順

[user@linuxhost ~]$ # === Windows7 上のフォルダを /mnt/src に mount
[user@linuxhost ~]$ sudo mount -t cifs "//win7host/src" /mnt/src -o username=user,password=pass,uid=500,gid=500,file_mode=0755,dir_mode=0755
[user@linuxhost ~]$ # === /mnt/src に移動
[user@linuxhost ~]$ cd /mnt/src
[user@linuxhost src]$ # === 簡単なPHPファイル作成
[user@linuxhost src]$ echo "<?php echo(\"TEST\n\");" > ./test.php
[user@linuxhost src]$ cat ./test.php
<?php echo("TEST\n");
[user@linuxhost src]$ # === 実行するとエラー
[user@linuxhost src]$ php ./test.php
PHP Fatal error:  Unknown: Failed opening required './test.php' (include_path='.:/usr/share/pear:/usr/share/php') in Unknown on line 0
[user@linuxhost src]$ # === リントでも Warning とエラー
[user@linuxhost src]$ php -l ./test.php
PHP Warning:  Unknown: Failed opening './test.php' for inclusion (include_path='.:/usr/share/pear:/usr/share/php') in Unknown on line 0
Errors parsing ./test.php


なお、上記で作成した /mnt/src/test.php を include() することは出来るので、ますます謎。

[user@linuxhost ~]$ # === mount ディレクトリ以外に移動
[user@linuxhost ~]$ cd ~
[user@linuxhost ~]$ # === /mnt/src/test.php を include() するPHPファイル作成
[user@linuxhost ~]$ echo "<?php include('/mnt/src/test.php');" > ./call_test.php
[user@linuxhost ~]$ cat ./call_test.php
<?php include('/mnt/src/test.php');
[user@linuxhost ~]$ # === ちゃんと実行される
[user@linuxhost ~]$ php ./call_test.php
TEST