PHP的CLI命令行運行模式淺析

在作開發的時候,咱們不只僅只是作各類網站或者接口,也常常須要寫一些命令行腳本用來處理一些後端的事務。好比對數據進行處理統計等。固然也是爲了效率着想,當一個事務有可能會有較長的耗時時,每每會交由服務器的定時器來固定時間調用腳本進行處理,從而讓客戶端可以有更好的用戶體驗。咱們今天就來了解下 PHP 的命令行運行模式,也就是 PHP CLI 。php

CLI 與 CGI

首先來看一下 CLI 和 CGI 的區別。咱們都知道,Nginx 使用的是 FastCgi 來調用 PHP 的服務。 CGI 是通用編程接口,也就是給調用者提供的一種使用本程序的接口。 Nginx 這種類型的服務器並非直接運行 PHP 程序的,而是經過 FastCgi 來執行 PHP 程序並得到返回結果。html

CLI 則是 Command Line Interface,即命令行接口。主要用做 PHP 的開發外殼應用。也就是用 PHP 來進行 shell 腳本的開發。相比 linux 原生的 shell 來講,固然是方便了許多。在命令行狀態下,直接使用 php 命令就能夠運行某段 PHP 代碼或某個 PHP 文件了。前端

另外,咱們在命令行也能夠直接使用 phpcgi 來運行一段 PHP 代碼或者某個 PHP 文件,它和直接使用 php 命令來運行有什麼區別呢?linux

  • CLI 的輸出沒有任何頭信息
  • CLI 在運行時,不會把工做目錄改成腳本的當前目錄
  • CLI 出錯時輸出純文本的錯誤信息(非 HTML 格式)
  • 強制覆蓋了 php.ini 中的某些設置,由於這些設置在外殼環境下是沒有意義的
// PHP的CLI命令行運行模式淺析.php
echo getcwd();

//  php-cgi dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php
// ...../MyDoc/博客文章/dev-blog/php/202004/source

// php dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php
// ...../MyDoc/博客文章

咱們選取最典型的一個例子,咱們運行的這個文件中,使用 getcwd() 輸出當前腳本運行的目錄,能夠看出兩種運行方式輸出的結果明顯不一樣。php-cgi 是以文件所在目錄爲基準輸出,而 php 則是以當前運行這個命令的目錄爲基準輸出。laravel

直接運行 PHP 代碼

在作一些簡單的調試的時候,咱們能夠直接經過 CLI 來運行一段代碼。git

// php -r "echo 121;"
// 121

也就是簡單的加個 -r 參數,後面跟上一段代碼,這段代碼必須用引號括起來。並且這個引號更推薦使用單引號,後面的例子會展現爲何用單引號更好。github

CLI 獲取參數

命令行模式下也是能夠給腳本傳遞參數的。shell

// PHP的CLI命令行運行模式淺析.php
print_r($argv);
// php-cgi dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php 1 2 3
// X-Powered-By: PHP/7.3.0
// Content-type: text/html; charset=UTF-8

// php dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php 1 2 3
// Array
// (
//     [0] => dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php
//     [1] => 1
//     [2] => 2
//     [3] => 3
// )

在測試文件中,咱們打印了 \$argv 變量。PHP 腳本運行的時候,會將命令行的全部參數保存在 $argv 變量中,而且還有一個 $argc 變量會保存參數的個數。編程

咱們依然是使用 php-cgi 和 php ,兩種模式來測試,從這裏咱們能發現 php-cgi 模式中 $argv 打印的內容居然是頭信息,而不是具體的參數信息。這也沒錯,畢竟 CGI 模式原本就是爲 Web 服務器提供的接口,因此它接收的是 post 、 get 這類的參數而不是命令行的參數。後端

CLI 模式下咱們正常得到了參數內容,而且 $argv[0] 始終保存的是當前運行文件及路徑。

CLI 命令行實用選項

最後,咱們再介紹一些命令行中經常使用的選項。

-r 直接運行代碼時的參數傳遞

// php -r "var_dump($argv);" app 
// Warning: var_dump() expects at least 1 parameter, 0 given in Command line code on line 1
// 雙引號 ",sh/bash 實行了參數替換

// php -r 'var_dump($argv);' app
// array(2) {
//     [0]=>string(19) "Standard input code"
//     [1]=>string(3) "app"
// }

// php -r 'var_dump($argv);' -- -h
// array(2) {
//     [0]=>string(19) "Standard input code"
//     [1]=>string(2) "-h"
// }

第一段代碼在對雙引號運行的 CLI 代碼進行參數傳遞的時候,會直接報警告。其實很好理解,雙引號裏面的$會讓系統的 sh/bash 覺得這是個變量從而進行變量參數替換。因此更推薦使用單引號進行平常的簡單測試。

第二段代碼可以正常打印傳遞進來的參數內容。第三行代碼則是須要傳遞帶 - 符號的內容時,須要先給一個 -- 參數列表分隔符。這是由於 -xxx 的內容會讓 php 命令認爲這是一個命令選項而不是參數,因此咱們添加一個分隔符就可讓分隔符以後的參數內容原樣傳遞進代碼中。

交互式地運行 PHP

// php -a
// php > $a = 1;
// php > echo $a;
// php > 1

添加一個 -a 選項,PHP 就會以交互式地形式運行,咱們能夠直接在交互狀態下寫代碼或運行任何內容。

查看 phpinfo() 及已經安裝的模塊

這兩個應該是你們常常會使用的兩個選項。

// 輸出 phpinfo()
// php -i

// 輸出 PHP 中加載的模塊
// php -m

// 查看模塊詳細信息
// php --ri swoole

另外咱們還能夠經過 --ri 模塊名 這個命令來查看具體某個擴展模塊的詳細信息。好比這裏咱們能夠查看到 swoole 擴展的版本及相關的配置信息。

查看某個文件

// 顯示去除了註釋和多餘空白的源代碼
// php -w dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php
// <?php
//  echo getcwd(); print_r($argv);

// 經過 linux 管道讀取輸入
// cat dev-blog/php/202004/source/PHP的CLI命令行運行模式淺析.php | php -r "print file_get_contents('php://stdin');"
// ......這個文件裏面全部的內容

最後兩個小技巧,一個是經過 -w 選項,咱們能夠打印這個 php 文件中全部非註釋和換行的內容。能夠當作是像前端的代碼壓縮同樣的能力。咱們這個測試文件中有很是多的註釋,經過這個命令後咱們打印出來的內容是去除掉全部註釋和空白行的結果。

另外一個是咱們能夠用 linux 管道的方式向 PHP CLI 發送數據。這裏咱們經過 cat 查看咱們的測試文件而後經過管道發送給 PHP CLI,在腳本中使用 STDIN 來讀取管道發送過來的內容完成了整個文件內容的打印。這裏咱們沒進行任何過濾,因此打印的是整個文件裏面的內容,你們能夠運行這個命令來測試。

總結

其實命令行模式運行的時候還有不少的選項,這裏咱們只是選取了一部分很是有用的內容進行展現。固然,大部分框架都提供了用於命令行的腳本框架,好比 laravel 中能夠經過 php artisan make:command 來建立命令行腳本,而後使用 php artisan 來運行框架中的腳本。這些內容未來咱們在學習框架方面知識的內容將會進行詳細的講解。

命令行 CLI 模式的應用很是普遍,幾乎任何項目中都會使用到,因此,深刻的學習掌握它將會使咱們大受裨益。

測試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202004/source/PHP%E7%9A%84CLI%E5%91%BD%E4%BB%A4%E8%A1%8C%E8%BF%90%E8%A1%8C%E6%A8%A1%E5%BC%8F%E6%B5%85%E6%9E%90.php

參考文檔:

https://www.php.net/manual/zh/features.commandline.php

各自媒體平臺都可搜索【硬核項目經理】

相關文章
相關標籤/搜索