System-Calls
getdents 在 2 個系統上返回不同結果的原因可能是什麼?
我有一個奇怪的情況,在一台伺服器上我得到以下結果:
vagrant@shopping:/vagrant/deployer-example$ uname -a Linux shopping 4.19.0-0.bpo.9-amd64 #1 SMP Debian 4.19.118-2+deb10u1~bpo9+1 (2020-06-09) x86_64 GNU/Linux vagrant@shopping:/vagrant/deployer-example$ bin/php --version PHP 8.0.3 (cli) (built: Mar 5 2021 08:36:11) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.3, Copyright (c) Zend Technologies with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies vagrant@shopping:/vagrant/deployer-example$ sudo ldd --version ldd (Debian GLIBC 2.24-11+deb9u4) 2.24 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper. vagrant@shopping:/vagrant/deployer-example$ php -r 'var_dump(glob("/vagrant/deployer-example/config/{routes}/*.yaml", GLOB_BRACE));' array(4) { [0]=> string(56) "/vagrant/deployer-example/config/routes/annotations.yaml" [1]=> string(55) "/vagrant/deployer-example/config/routes/easy_admin.yaml" [2]=> string(52) "/vagrant/deployer-example/config/routes/monitor.yaml" [3]=> string(59) "/vagrant/deployer-example/config/routes/nelmio_api_doc.yaml" } vagrant@shopping:/vagrant/deployer-example$ php -r 'var_dump(glob("/vagrant/deployer-example/config/{routes}/*.yaml/", GLOB_BRACE));' array(4) { [0]=> string(56) "/vagrant/deployer-example/config/routes/annotations.yaml" [1]=> string(55) "/vagrant/deployer-example/config/routes/easy_admin.yaml" [2]=> string(52) "/vagrant/deployer-example/config/routes/monitor.yaml" [3]=> string(59) "/vagrant/deployer-example/config/routes/nelmio_api_doc.yaml" }
但是在第二個系統上
deployer-example@s2-stg-s01:~/deployer/current$ uname -a Linux s2-stg-s01 4.19.0-0.bpo.9-amd64 #1 SMP Debian 4.19.118-2+deb10u1~bpo9+1 (2020-06-09) x86_64 GNU/Linux deployer-example@s2-stg-s01:~/deployer/current$ bin/php --version PHP 8.0.3 (cli) (built: Mar 5 2021 08:36:11) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.3, Copyright (c) Zend Technologies with Zend OPcache v8.0.3, Copyright (c), by Zend Technologies deployer-example@s2-stg-s01:~/deployer/current$ ldd --version ldd (Debian GLIBC 2.24-11+deb9u4) 2.24 Copyright © 2016 Free Software Foundation, Inc. Dies ist freie Software; in den Quellen befinden sich die Lizenzbedingungen. Es gibt KEINERLEI Garantie; nicht einmal für die TAUGLICHKEIT oder VERWENDBARKEIT FÜR EINEN ANGEGEBENEN ZWECK. Implementiert von Roland McGrath und Ulrich Drepper. deployer-example@s2-stg-s01:~/deployer/current$ php -r 'var_dump(glob("/home/deployer-example/deployer/releases/437/config/{routes}/*.yaml", GLOB_BRACE));' array(4) { [0]=> string(75) "/home/deployer-example/deployer/releases/437/config/routes/annotations.yaml" [1]=> string(74) "/home/deployer-example/deployer/releases/437/config/routes/easy_admin.yaml" [2]=> string(71) "/home/deployer-example/deployer/releases/437/config/routes/monitor.yaml" [3]=> string(78) "/home/deployer-example/deployer/releases/437/config/routes/nelmio_api_doc.yaml" } deployer-example@s2-stg-s01:~/deployer/current$ php -r 'var_dump(glob("/home/deployer-example/deployer/releases/437/config/{routes}/*.yaml/", GLOB_BRACE));' array(0) { }
我正在用 strace 調試它,發現對於第一個系統它報告:
open("/vagrant/deployer-example/config/routes", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 3 fstat(3, {st_dev=makedev(0, 44), st_ino=86530891, st_mode=S_IFDIR|0755, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=224, st_atime=2021-03-12T15:24:14+0000, st_mtime=2021-03-12T15:19:23+0000, st_ctime=2021-03-12T15:19:23+0000}) = 0 brk(0x562b5bb63000) = 0x562b5bb63000 getdents(3, [{d_ino=1031795, d_off=1, d_reclen=24, d_name=".", d_type=DT_UNKNOWN}, {d_ino=1031796, d_off=2, d_reclen=24, d_name="..", d_type=DT_UNKNOWN}, {d_ino=1031797, d_off=3, d_reclen=40, d_name="annotations.yaml", d_type=DT_UNKNOWN}, {d_ino=1031798, d_off=4, d_reclen=24, d_name="dev", d_type=DT_UNKNOWN}, {d_ino=1031799, d_off=5, d_reclen=40, d_name="easy_admin.yaml", d_type=DT_UNKNOWN}, {d_ino=1031800, d_off=6, d_reclen=32, d_name="monitor.yaml", d_type=DT_UNKNOWN}, {d_ino=1031801, d_off=7, d_reclen=40, d_name="nelmio_api_doc.yaml", d_type=DT_UNKNOWN}], 32768) = 224 newfstatat(3, "annotations.yaml", {st_dev=makedev(0, 44), st_ino=87279600, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=135, st_atime=2021-03-12T15:19:24+0000, st_mtime=2021-03-12T15:19:23+0000, st_ctime=2021-03-12T15:19:23+0000}, 0) = 0 newfstatat(3, "easy_admin.yaml", {st_dev=makedev(0, 44), st_ino=87279603, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=127, st_atime=2021-03-05T16:00:41+0000, st_mtime=2021-03-05T16:00:41+0000, st_ctime=2021-03-05T16:00:41+0000}, 0) = 0 newfstatat(3, "monitor.yaml", {st_dev=makedev(0, 44), st_ino=87279604, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=137, st_atime=2021-03-05T16:00:41+0000, st_mtime=2021-03-05T16:00:41+0000, st_ctime=2021-03-05T16:00:41+0000}, 0) = 0 newfstatat(3, "nelmio_api_doc.yaml", {st_dev=makedev(0, 44), st_ino=87279605, st_mode=S_IFREG|0644, st_nlink=1, st_uid=1000, st_gid=1000, st_blksize=4096, st_blocks=8, st_size=367, st_atime=2021-03-05T16:00:41+0000, st_mtime=2021-03-05T16:00:41+0000, st_ctime=2021-03-05T16:00:41+0000}, 0) = 0 getdents(3, [], 32768) = 0 close(3) = 0
但對於第二個
open("/home/deployer-example/deployer/releases/437/config/routes", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5 fstat(5, {st_dev=makedev(8, 17), st_ino=123601048, st_mode=S_IFDIR|0755, st_nlink=3, st_uid=1084, st_gid=1084, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=2021-03-12T16:18:27+0100.512902323, st_mtime=2021-03-12T16:17:55+0100.984164843, st_ctime=2021-03-12T16:17:55+0100.984164843}) = 0 brk(0x557145c2a000) = 0x557145c2a000 getdents(5, [{d_ino=123601055, d_off=2396884471359371616, d_reclen=40, d_name="nelmio_api_doc.yaml", d_type=DT_REG}, {d_ino=123601053, d_off=2713394375622026215, d_reclen=32, d_name="monitor.yaml", d_type=DT_REG}, {d_ino=123601049, d_off=3087430337415459848, d_reclen=40, d_name="easy_admin.yaml", d_type=DT_REG}, {d_ino=123601050, d_off=7440370618885146051, d_reclen=24, d_name="dev", d_type=DT_DIR}, {d_ino=123600993, d_off=8681975314043990400, d_reclen=24, d_name="..", d_type=DT_DIR}, {d_ino=123601479, d_off=9220757504948275036, d_reclen=40, d_name="annotations.yaml", d_type=DT_REG}, {d_ino=123601048, d_off=9223372036854775807, d_reclen=24, d_name=".", d_type=DT_DIR}], 32768) = 224 getdents(5, [], 32768) = 0 close(5) = 0
兩個系統都在相同的 Debian 版本下執行,在 EXT4 文件系統下執行,並且配置了相同的 Ansible 腳本,因此也應該具有相同的核心包。
我怎樣才能把它縮小到罪魁禍首?有什麼可能的原因導致這兩個伺服器的行為不同?
由於 strace enabled ( ) 中的詳細模式可以看出
-v
,這些 getdents 呼叫d_type=DT_REG
在第一個系統上返回,但在第二個系統上返回d_type=DT_UNKNOWN
。這樣做的原因是,雖然在第一種情況下使用的文件系統是ext4
,但在第二種情況下是prl_fs
。prl_fs
文件系統本身顯然不會返回 knownd_type
。這會在 glibc 中的 glob() 函式中觸發邊緣情況。在https://sourceware.org/bugzilla/show_bug.cgi?id=25659報告了一個 glibc 錯誤問題
我還聯繫了 Parallels 支持,要求他們停止將 DT_UNKNOWN 作為 d_type 返回。從 Parallels 16.5.0-49183 開始,他們修復了這個問題:)