PHP 日本研討會 2024

system

(PHP 4, PHP 5, PHP 7, PHP 8)

system執行外部程式並顯示輸出

描述

system(string $command, int &$result_code = null): string|false

system() 就像 C 語言版本的函式一樣,會執行指定的 command 並輸出結果。

如果 PHP 以伺服器模組執行,system() 呼叫也會嘗試在每次輸出後自動清除網頁伺服器的輸出緩衝區。

如果您需要執行命令並將命令中的所有資料直接傳回而不受任何干擾,請使用 passthru() 函式。

參數

command

將被執行的命令。

result_code

如果存在 result_code 引數,則執行命令的回傳狀態將會寫入此變數。

回傳值

成功時回傳命令輸出的最後一行,失敗時回傳 false

範例

範例 1:system() 範例

<?php
echo '<pre>';

// 輸出 shell 命令 "ls" 的所有結果,並將最後一行輸出傳回
// 到 $last_line。將 shell 命令的回傳值儲存於 $retval。
$last_line = system('ls', $retval);

// 列印額外資訊
echo '
</pre>
<hr />Last line of the output: '
. $last_line . '
<hr />Return value: '
. $retval;
?>

注意

警告

當允許使用者提供的資料傳遞到此函式時,請使用 escapeshellarg()escapeshellcmd() 來確保使用者無法欺騙系統執行任意命令。

注意:

如果使用此函式啟動程式,為了讓程式在背景繼續執行,程式的輸出必須重新導向到檔案或其他輸出串流。否則會導致 PHP 掛起,直到程式執行結束。

另請參閱

新增註解

使用者提供的註解 18 則註解

64
no at mail dot com
12 年前
這是給 WINDOWS 使用者的。我正在執行 Apache,我已經花了好幾個小時嘗試擷取命令的輸出。

我試過了這裡寫的所有內容,然後繼續在線上搜尋,但都毫無結果。永遠無法擷取到命令的輸出。我得到的只是一個空的陣列。

最後,我在某個了不起的傢伙的部落格中找到了一則留言,解決了我的問題。

在命令名稱中加入字串「2>&1」終於傳回了輸出!這在 PHP 的 exec() 和 system() 中都有效,因為它使用串流重新導向將輸出重新導向到正確的位置!

system("您的命令名稱 2>&1",$output) ;
13
dan at thecsl dot org
18 年前
您可能想要檢查系統呼叫是否有錯誤。慣例是回傳 0 表示「無錯誤」,這與 FALSE 相同,可能會造成混淆。您需要做類似的事情

<?php
$cmd
= "/usr/bin/pngtopnm $png_file > $pnm_file";
system($cmd,$return_value);
(
$return_value == 0) or die("傳回錯誤: $cmd");
?>
8
mortoray at ecircle-ag dot com
20 年前
如果您使用「php.ini」選項,請勿使用「system」
zlib.output_compression = On

這樣做會導致瀏覽器收到垃圾資料(我猜測標頭/緩衝區會搞混)。

在這種情況下請使用 passthru,它似乎可以如預期般運作。
6
timgolding_10 at hotmail dot com
17 年前
這是使用 system 在 linux 伺服器上呼叫檔案命令的範例。此指令碼會偵測使用者發佈的檔案是否為 jpeg、gif 或 png

<?PHP

$accepted_types
=array("JPEG" , "GIF", "PNG");

// 儲存上傳檔案於伺服器上的暫存檔名。
if(!empty($_FILES["uploadedfile"]))
{
$uploaddir = $_SERVER['DOCUMENT_ROOT']."/images/";
$uploaddir.=basename( $_FILES['uploadedfile']['name']);

// 使用 Linux FILE 指令驗證檔案
$last_line = system('file '.escapeshellarg($_FILES['uploadedfile']['tmp_name']), $retval);

// 從 magic database 取得檔案副檔名
$splitvals=explode(' image data' , $last_line);
$vals=explode(':', $splitvals[0]);
$vals[1]=str_replace(' ','', $vals[1]);

if (
in_array($vals[1], $accepted_types))
{
echo
$vals[1].' 已接受 <br />';
if(!
file_exists($uploaddir)){
// 將檔案複製到永久位置
if(move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], $uploaddir))
{
echo
$uploaddir." 上傳成功! <br />";
}
else
{
echo
"上傳新檔案時發生問題,請聯絡管理員。";
}
}
else echo
'此檔案已存在於資料庫中,上傳前請重新命名檔案';
}
}else echo
$_FILES['uploadedfile']['error'].'<br />';
?>
4
ccurtis at aet-usa dot com
25 年前
如果沒有輸出任何標頭,呼叫 system() 函式會將標頭刷新至客戶端並插入一個換行符號;後續將不會有任何標頭或 Cookie 傳輸至瀏覽器。在 3.0.7 版本中,你不會收到 Header() 函式失敗的警告,但如果你嘗試設定 Cookie 會收到警告。如果你想在函式呼叫後繼續發送標頭,請改用 exec()。
4
nospam at php dot net
24 年前
如果你試圖將需要參數的 CGI 腳本解析到你的網頁伺服器,請查看 virtual() 函式...我花了很久才發現它存在...
它的用法如下
<?php
virtual
("/cgi-bin/lastuser.cgi?argument");
?>
現在對我來說運作良好
3
Jim Belton
21 年前
要從 PHP CLI 腳本執行全螢幕程式,請將輸入和輸出重新導向至 /dev/tty。例如

system("timeconfig > /dev/tty < /dev/tty");

System 會等待程式執行完成後才繼續。
1
Anonoymous
5 年前
Windows 需要 GUI 的指令。

關於此主題的許多資訊都來自 2010-2012 年,並且指的是 XP,基本上都無法運作。我正在 Windows 7 中使用 apache/php/mysql。

當在 Windows 中需要一個帶有 GUI 的系統指令時 - 例如 Labview 可執行檔、記事本等...,其他人提到了 sysinternals 的 psexec 指令,因為 cmd /c 不會運作,但具體用法沒有明確定義。以下是在 Windows 7 上對我有效的做法

system('C:/nttools/2019/psexec \\\\10.100.100.101 -i -u administrator -p password -accepteula -nobanner C:\\htdocs\\test\\test.bat');

psexec 可執行檔的路徑使用正斜線,遠端 PC 網路位置(實際上是本機 PC,不是遠端)是 \\ip_address,每個反斜線都需要額外的反斜線,因此需要 4 個 \'s。

psexec 要執行的指令路徑需要反斜線,這也需要雙反斜線。

-i 選項用於互動式程式,並且是正確執行所必需的,否則它會顯示在工作管理員中,但如果給予命令列參數,則不會顯示或正確執行。

-accepteula -nobanner 是為了抑制 sysinternals 關於其授權的訊息框。

我的執行指令非常長,其中包含多個命令列輸入,其中許多都用雙引號括起來,所以我認為將其放在批次檔中並直接呼叫批次檔是最簡單的。運作良好,載入網頁的遠端使用者會導致可執行檔在網頁伺服器上彈出,進行分析然後消失。Labview 可以使用 active-x 函式讀取原生 excel 檔案,並寫入 mysql 資料庫以儲存結果等,因此這是一個非常強大的功能組合。
2
vdweij at hotmail dot com
19 年前
可以只捕獲錯誤流 (STERR)。方法如下...

(some_command par1 par2 > /dev/null) 3>&1 1>&2 2>&3

-首先,STDOUT 會重新導向至 /dev/null。
-透過使用括號,可以重新控制 STERR 和 STOUT。
-然後將 STERR 與 STOUT 交換。

此交換使用標準變數交換方法 -- 需要 3 個變數(儲存桶)才能將 2 個變數彼此交換。(你有 2 個變數,你需要交換內容 - 你必須引入第 3 個臨時變數來儲存其中一個值,以便你可以正確地交換它們)。

這個連結提供了我這些資訊
http://www.cpqlinux.com/redirect.html
2
morris_hirsch at hotmail dot com
21 年前
另一個使用 shell_exec 而不是 system 的原因是當結果是多行時,例如 grep 或 ls

<?php

// 這會正確將答案字串設定為所有找到的行
//$answer = shell_exec ("grep 'set of color names' *.php ");
//echo "answer = $answer";

// 這會將所有行傳遞到輸出(它們會顯示在頁面上)
// 並將答案字串設定為最後一行
$sys = system ("grep 'set of color names' *.php ");
echo
"sys =(($sys))";

?>

這是 system 呼叫產生的檢視/原始碼

setprefs.php:// 標準的顏色名稱集合為
setprefs.php:// 大多數瀏覽器接受更廣泛的顏色名稱集合
silly.php: //$answer = shell_exec ("grep 'set of color names' *.php ");
silly.php: $sys = system ("grep 'set of color names' *.php ");
sys =((silly.php: $sys = system ("grep 'set of color names' *.php ");))

這是使用 shell_exec 的檢視原始碼

answer = setprefs.php:// 標準的顏色名稱集合為
setprefs.php:// 大多數瀏覽器接受更廣泛的顏色名稱集合
silly.php: $answer = shell_exec ("grep 'set of color names' *.php ");
silly.php:// $sys = system ("grep 'set of color names' *.php ");
1
d dot kraft at szo dot de
21 年前
對於在網頁伺服器內運行的 PHP

當透過以下方式呼叫程序時
system("your_process &");
使其在背景中執行,請注意當網頁伺服器重新啟動時,此程序會被終止。
0
kexianin at diyism dot com
15 年前
如果你看不到 system()、shell_exec() 等的任何輸出或錯誤,你可以嘗試以下方法

<?php
function my_exec($cmd, $input='')
{
$proc=proc_open($cmd, array(0=>array('pipe', 'r'), 1=>array('pipe', 'w'), 2=>array('pipe', 'w')), $pipes);
fwrite($pipes[0], $input);fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]);fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]);fclose($pipes[2]);
$rtn=proc_close($proc);
return array(
'stdout'=>$stdout,
'stderr'=>$stderr,
'return'=>$rtn
);
}
var_export(my_exec('echo -e $(</dev/stdin) | wc -l', 'h\\nel\\nlo'));
?>

例如,"echo shell_exec('ls');" 不會有任何輸出,
"my_exec('ls');" 會得到 "sh: ls: command not found" 的錯誤訊息,
"my_exec('/bin/ls');" 可能會得到 "sh: /bin/ls: Permission denied" 的錯誤訊息,
而這個權限問題可能是由 SELinux 造成的。
0
grytolle at gmail dot com
15 年前
這是一個變通方法,可以讓程式在其自身的目錄中執行,而不是在腳本的目錄中。

使用範例
<?php runAsynchronously("c:\games\jazz2\jazz2.exe","-connect 1.2.3.4"); ?>

<?php
function runAsynchronously($path,$arguments) {
$WshShell = new COM("WScript.Shell");
$oShellLink = $WshShell->CreateShortcut("temp.lnk");
$oShellLink->TargetPath = $path;
$oShellLink->Arguments = $arguments;
$oShellLink->WorkingDirectory = dirname($path);
$oShellLink->WindowStyle = 1;
$oShellLink->Save();
$oExec = $WshShell->Run("temp.lnk", 7, false);
unset(
$WshShell,$oShellLink,$oExec);
unlink("temp.lnk");
}
?>
0
vlad dot sharanhovich at gmail dot com
16 年前
在 Windows 平台上雙引號的問題,先前在評論中討論過,在 PHP 5.2.5 中仍然存在。如果 $command 包含超過 2 個 " 字元,則無法執行 system($command)。system('"echo" A'); 可以運作,但 system('"echo" "A"'); 則不行。請搜尋評論,其中發布了一個解決方案,透過暫時的 .bat 檔案來解決這個問題。
-1
Daniel Morris (danielxmorris.com)
16 年前
如何使用 PHP 發出系統嗶聲。

<?php
function beep ($int_beeps = 1) {
for (
$i = 0; $i < $int_beeps; $i++): $string_beeps .= "\x07"; endfor;
isset (
$_SERVER['SERVER_PROTOCOL']) ? false : print $string_beeps;
}

?>

當透過瀏覽器執行時,這不會執行任何操作;如果透過 shell 執行,則會發出 $int_beeps 次的聲音嗶聲。這應該可以在 Windows、Unix 等系統上運作。
-1
eric_REMOVE at movementmovement_REMOVE dot com
20 年前
重要的是要注意,如果您在迴圈中執行一系列 system() 命令,您需要包含第二個參數,它們才會同步執行。

例如)

// 這將異步執行 process.php;不會等待完成才執行下一個。
$array = array('apple', 'banana', 'pear');
foreach($array as $i)
{
system("php process.php \"fruit=$i\"");
}

// 這將執行 process.php 3 次,在開始新的命令之前,會等待先前的命令完成
$array = array('apple', 'banana', 'pear');
foreach($array as $i)
{
system("php process.php \"fruit=$i\"", $status);
}
-2
lc at _REMOVE__THIS_lc dot yi dot org
21 年前
回覆:cpmorris at hotmail dot com 和 WINNT。

我剛花了一些時間學習如何使用 php system 函數。我成功讓長檔名可以運作。似乎您需要採取與批次檔、WSH 和大多數其他在 WinNT/2K/XP 下使用的程式語言相同的方法。將路徑 + 檔名用雙引號括起來似乎可以運作。所以,像這樣應該可以為您工作

"c:\program files\apache group\apache2\bin\htpasswd"

請注意,如果您有參數,它們會放在最後一個引號之外。哦,別忘了跳脫斜線和引號!

我不知道 htpasswd 的參數是什麼,但讓我們假設

$cmd="\"c:\\program files\\apache group\\apache2\\bin\\htpasswd\" username password";
$str=system($cmd);

希望這對某些人有幫助!

Leonard
http:\\www.lc.yi.org
-3
cnoelker at softpearls dot de
21 年前
嗨,
一些關於在 Windows 電腦上使用 system() 呼叫批次檔的提示
* 使用雙反斜線撰寫可執行檔的路徑,如下所示
C:\\path\\to\\prog.exe
* 如果您要參考其他路徑,例如作為參數,則使用一個反斜線即可。
* 不要使用 SET 來宣告參數 - 這行不通!範例
SET PATH="C:\path\to\lib"
echo path is %PATH%
這從命令列啟動時可以正常運作,但從 PHP 呼叫時,變數只是空的。
To Top