PHP CLI模式開發不需要任何一種Web服務器(包括Apache或MS IIS等),這樣,CLI可以運行在各種場合。
有兩種方法可以運行PHP CLI腳本。
第一種方法是使用 # php /path/to/yourFile.php 調用PHP CLI解釋器,並給腳本傳遞參數。這種方法要指定php解釋器的路徑。
第二種方法是首先運行chmod +x <要運行的腳本文件名>(UNIX/Linux環境),將該PHP文件置為可執行權限,然后在CLI腳本頭部第一行加入聲明(類似於#! /usr/bin/php 或 PHP CLI 解釋器位置),接着在命令行直接執行。
一、從命令行上讀取參數
如果想從命令行獲取參數,CLI可以從 $_SERVER['argv'] 和 $_SERVER['argc'] 取得參數的值和參數個數。
我們建立一個文件,名字為 cliPHP1.php 腳本代碼如下:
#! /usr/local/php/bin/php -q <?php /** * PHP CLI帶有兩個特殊的變量,專門用來達到這個目的: * 一個是 $_SERVER['argv'] 變量,它通過命令行把傳遞給PHP腳本的參數保存為單獨的數組元素; * 另一是 $_SERVER['argc'] 變量,它用來保存$_SERVER['argv']數組里元素的個數。 * * * 運行效果: * # /usr/local/php/bin/php ./cliPHP1.php aa bb cc * Array * ( * [0] => ./cliPHP1.php ---> 0 指當前腳本名稱 * [1] => aa --------------> 1 第1個參數 * [2] => bb --------------> 2 第2個參數 * [3] => cc --------------> n 第n個參數 * ) * number: 4 -----------------> 參數數量 * */ ini_set('error_reporting', 'E_ALL & ~E_NOTICE'); //設置錯誤報告模式 $argv = $_SERVER['argv']; //獲取參數(array 數組) $argc = $_SERVER['argc']; //獲取參數數量(integer 整數) print_r($argv); echo 'number: '.$argc; echo "\r\n"; ?>
二、處理I/O通道
PHP最初設計不是用於與用戶直接的鍵盤輸入或文本輸出結合使用。了解這一設計是至關重要的,因為如果需要在命令行中執行任何操作,都必須能夠與用戶來回通信。
輸入輸出(I/O)通道這個思想來源於UNIX系統,UNIX系統提供3個文件句柄,用以從一個應用程序及用戶終端發送和接收數據。
我們可以把一個腳本的輸出重定向到一個文件,例如:
# php world.php > outputfile
如果是在UNIX系統下,也可以使用通道定向到另一個命令或應用程序中。例如:
# php world.php | sort
在PHP 5 CLI中,有一個文件流句柄,可以使用3個系統常量,分別為 STDIN、 STDOUT 和 STDERR。下面我們分別介紹。
(1) STDIN
STDIN 全稱為 standard in 或 standard input 標准輸入可以從終端取得任何數據。
(2) STDOUT
STDOUT 全稱為 standard out 或 standard output 標准輸出可以直接輸出到屏幕(也可以輸出到其他程序,使用STDIN取得),如果在PHP CLI模式里使用print或echo語句,則這些數據將發送到STDOUT。
(3) STDERR
STDERR 全稱為 standard error 在默認情況下會直接發送至用戶終端,當使用STDIN文件句柄從其他應用程序沒有讀取到數據時會生成一個“stdin.stderr”。
我們建立一個文件,名字為 cliPHP2.php 腳本代碼如下:
#! /usr/local/php/bin/php -q <?php /** * 本例是一個CLI與用戶交互腳本,讓其輸出用戶名與年齡並輸出 * 標准輸出: fwrite(STDOUT,'請輸出用戶名:') //輸出內容 * 標准輸入: fgets(STDIN) //獲取用戶輸入的內容 * 標准錯誤輸出: fwrite(STDERR,'錯誤:xxxxx') //輸出錯誤信息 * * 運行效果: * [root@zzx tmp]# /usr/local/php/bin/php /wwwroot/test/httpsqs/cliPHP.php * Enter your name: * Enter your name:zhangsan * Enter your age:abc * Notice: age must be an integer,try again! * Enter your age:aaa * Notice: age must be an integer,try again! * Enter your age:22 * Hello zhangsan, your age is 22 */ $name = ''; $age = ''; while(true){ fwrite(STDOUT,"Enter your name:"); //標准輸出,等待用戶輸入用戶名 $name = trim(fgets(STDIN)); //標准輸入,立即獲取用戶名 if(!empty($name)){ break 1; } } while(true){ fwrite(STDOUT,"Enter your age:"); $age = trim(fgets(STDIN)); if(empty($age)){ continue 1; } $matchNum = preg_match('/^\d+$/',$age); //驗證整型,獲取匹配次數 if($matchNum == 0){ fwrite(STDERR,"Notice: age must be an integer,try again!\r\n"); }else{ break 1; } } //do something here... $outStr = "Hello $name, your age is $age"; fwrite(STDOUT,$outStr); echo "\n\n"; ?>
三、用 nohup 后台運行CLI
如果正在運行一個進程,而且在退出賬戶時該進程還不會結束,即在系統后台或背景下運行,那么就可以使用nohup命令。該命令可以在退出賬戶之后繼續運行相應的進程。
nohup在英文中就是不掛起的意思(no hang up)。該命令的一般形式為:
# nohup <腳本名.php> &
使用nohup命令提交作業,在默認情況下該作業的所有輸出都被重定向到一個名為 nohup.out 的文件中,除非另外指定了輸出文件:
# nohup /usr/local/php/bin/php ./scriptName.php 1>/tmp/log.txt & 將標准輸出重定向到log.txt # nohup /usr/local/php/bin/php ./scriptName.php 1>/tmp/log.txt 2>/tmp/err.txt & 將標准輸出重定向到/tmp/log.txt 錯誤輸出重定向到/tmp/err.txt # nohup /usr/local/php/bin/php ./scriptName.php 1>/tmp/log.txt 2>&1 & 將標准輸出重定向到/tmp/log.txt 然后再將標准錯誤輸出重定向到標准輸出,即:兩者一起重定向到/tmp/log.txt # nohup /usr/local/php/bin/php ./scriptName.php 1>/dev/null 2>&1 & 將標准輸出和錯誤輸出一起到重定向到/dev/null
這樣,PHP CLI腳本執行后的結果將輸出到log.txt中,我們可以使用tail命令動態查看內容:
# tail -f -n20 /tmp/log.txt
現在再來實現一個例子,是每隔10秒鍾自動生成一個靜態HTML文件,並一直執行下去。腳本代碼如下:
腳本名稱: cliPHP3.php
#! /usr/local/php/bin/php -q <?php /** * 本例是每隔10秒鍾自動生成一個靜態HTML文件,並一直執行下去 */ while(true){ file_put_contents("/tmp/article_".time().".html",date('Y-m-d H:i:s')); sleep(10); //10秒 (單位: 秒) //usleep(1000000 * 0.5); //0.5秒(單位: 微秒 注: 1000000微秒=1秒) } ?>
保存並且退出vi編輯器,然后賦予 genHTML.php 文件可執行權限,並執行(在Linux命令行下執行腳本建議寫絕對路徑,這是良好習慣):
# chmod 755 cliPHP3.php
# nohup /usr/local/php/bin/php /wwwroot/httpsqs/cliPHP3.php 1>/dev/null 2>&1 &
執行上述命令后出現如下提示:[2] 3300
在當前會話下,使用jobs命令可以查看所有后台運行的所有進程:
# jobs
[1]- Running nohup /usr/local/php/bin/php /wwwroot/httpsqs/usage_server.php > /opt/httpsqs/data/log.txt 2> /opt/httpsqs/data/err.txt &
[2]+ Running nohup /usr/local/php/bin/php /wwwroot/httpsqs/cliPHP3.php > /dev/null 2>&1 &
如何終止CLI程序的后台運行呢?
使用 # ps aux 可查看當前系統所有進程,使用grep過濾選項即可,如下:
# ps aux | grep php
root 3227 0.1 1.6 106796 8408 pts/3 S 06:03 0:02 /usr/local/php/bin/php /wwwroot/httpsqs/usage_server.php
root 3300 0.0 1.5 106796 8080 pts/3 S 06:39 0:00 /usr/local/php/bin/php /wwwroot/httpsqs/cliPHP3.php
root 3312 0.0 0.1 5980 744 pts/4 S+ 06:41 0:00 grep php
能夠輕松找到 /wwwroot/httpsqs/cliPHP3.php 對應的PID為3300,使用kill命令殺死進程即可:
# kill 3300