Apache-2.2

通過 exec() 執行 rsync 的 apache/mod_php 問題

  • August 30, 2012

我在我的一台伺服器上執行 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>

到目前為止,這是我所知道的:

  1. 從 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,並且腳本執行通過瀏覽器執行良好。

引用自:https://serverfault.com/questions/420120