Apache-2.2
通過 exec() 執行 rsync 的 apache/mod_php 問題
我在我的一台伺服器上執行 rsync 的 php 腳本存在問題,但僅在通過 apache/mod_php 執行時。
這是腳本的精簡版:
<?php exec("rsync -a /var/www/html/from/ /var/www/html/to"); ?>
很簡單。此命令的目的是將文件夾結構(具有適當權限)複製到新文件夾。但問題是,這個 rsync 命令掛起並且不會完成。
做了一些調查,我注意到腳本會產生兩個 rsync 程序:
> ps aux | grep rsync apache 20752 56.9 0.0 10400 656 ? R 11:29 1:37 rsync -a /var/www/html/from/ /var/www/html/to apache 20753 0.0 0.0 10400 276 ? S 11:29 0:00 rsync -a /var/www/html/from/ /var/www/html/to root 22305 0.0 0.0 61212 764 pts/1 S+ 11:32 0:00 grep rsync
我注意到第一個程序處於“執行”狀態。所以我對它做了一個 strace,但我得到的輸出如下:
> strace -p 20752 <snip> select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) select(1037, [1026 1027 1028 1029], [], NULL, {60, 0}) = 4 (in [1026 1027 1028 1029], left {60, 0}) <snip>
到目前為止,這是我所知道的:
- 從 cli 執行時,php 腳本工作正常。我啟用
su apache
並執行腳本的能力> php myscript.php
,它工作正常。但是執行http://mydomain.com/myscript.php會創建 2 個程序,其中第一個程序中的一個處於持續執行狀態。這使我相信這不是許可問題。作為進一步的證明,這裡是ls -l
輸出:> ls -l /var/www | grep html drwxr-xr-x 79 apache apacheftp 4096 Aug 17 12:07 html > ls -l /var/www/html | grep from drwxrwxr-x 2 apache apache 4096 Aug 22 11:27 from
因此,apache 有權寫入目錄,並從 from 目錄讀取。 2. 在相同規格的不同伺服器上執行相同的腳本可以正常工作。兩台伺服器的規格是:
Apache version: Apache/2.2.3 PHP version: 5.3.3 rsync version: 2.6.8 protocol version 29 OS: Red Hat Enterprise Linux Server release 5.6 (Tikanga)
我不知道的是為什麼 apache 會產生兩個 rsync 程序(或者為什麼第一個 rsync 會產生第二個),以及為什麼第一個 rsync 程序似乎被卡住了
select(1037...)
有人可以解釋一下嗎?
因此,在修改我的腳本以直接通過
exec()
函式執行 strace 之後,如下所示:/usr/bin/strace -fo /var/www/html/rsynce.log /usr/bin/rsync -a /var/www/html/from/ /var/www/html/to
並檢查通過瀏覽器執行生成的文件的差異,從命令行,我發現了這一行(在瀏覽器執行腳本生成的日誌中):
select(1034, [1026 1027 1028 1029], [], NULL, {60, 0}) = -1 EBADF (Bad file descriptor)
這讓我研究了 apache 中的文件描述符。在我的設置中,我執行了許多虛擬主機,每個虛擬主機都定義了 3 個唯一的日誌文件。因此,當 apache 程序使用 1143 個文件描述符(通過
lsof -p pid | wc -l
)時,其中只有 124 個不是日誌。我能夠從虛擬主機中刪除唯一的日誌文件,重新啟動 apache,並且腳本執行通過瀏覽器執行良好。