php cli編程 命令行模式相關知識點

在命令行下執行php腳本,一般我們可以這麼做:

1、demo1.php

<?php
echo "hello php\n";

然後執行腳本就是:

php demo1.php

執行結果:

2、demo2.php ,執行 

which php

查看php腳本命令在哪裏,例如我的就是: /usr/local/php/bin/php,那我們就可以這麼寫demo2.php:

#!/usr/local/php/bin/php
<?php
echo "hello php\n";

然後執行 chmod +x demo2.php ,將demo2.php設置成可執行文件,就跟我們寫shell一樣的方式,執行腳本就無需前綴php了,直接 ./demo2.php 即可。

./demo2.php

兩種方式都可以,一般寫的php腳本是用於crontab定時任務,建議採用第二種方式編寫。

現在我們來介紹相關知識點:

1、cli編程,命令行模式下, cookie、session這些機制都是沒用的,所以不要使用這些內置的超全局變量。session_start 也是白費勁的,會生成session文件,下次執行又會生成一個文件,浪費性能不說,session文件還佔空間。下面舉一個反例子,切記,不要這麼用:

<?php
session_save_path(__DIR__);
session_start();

執行兩次 php demo3.php ,然後 ll 查看文件列表,會多出兩個沒用的session文件。

2、set_time_limit 無效,命令行模式本身是無超時機制的,所以無需這麼寫了。

3、PHP版本判斷,PHP_VERSION常量 、version_compare 函數,可以方便我們做一些兼容性處理,這不僅僅可以用在cli上。

下面就是一個例子,php7.1.0 提供了一個新的函數,pcntl_async_signals 用來代替  pcntl_signal_dispatch ,爲了兼容低版本的php,我們可以這麼寫,以便兼容多個版本。

#!/usr/local/php/bin/php
<?php
 
if(version_compare(PHP_VERSION, '7.1.0')>=0){
    pcntl_async_signals(true);
}
 
pcntl_signal(SIGINT, function(){
   echo "信號觸發\n";
});
 
 
$i=0;
while(true){
    if(version_compare(PHP_VERSION, '7.1.0')<0){
        pcntl_signal_dispatch();
    }
    $i++;
    echo $i,"\n";
    sleep(1);    
}

4、設置進程名 cli_set_process_title、setproctitle ,執行php腳本的時候,我們可以利用下面的代碼,給我們的進程設置名字,方便我們的查找和判斷,例如一個長時間執行的腳本,一次只能執行一個,不能重複執行,我們可以給程序設置名字,執行的時候,查詢下,當前進程是否有執行的進程名,即可判斷是否重複執行了。

<?php

$pid = trim(`pidof learnPHPcli`);
if (!empty($pid)) {
    exit('sorry');
}

function set_process_title($title)
{
    set_error_handler(function () {});
    // >=php 5.5
    if (function_exists('cli_set_process_title')) {
        cli_set_process_title($title);
    } // Need proctitle when php<=5.5 .
    elseif (extension_loaded('proctitle') && function_exists('setproctitle')) {
        setproctitle($title);
    }
    restore_error_handler();
}

set_process_title("learnPHPcli");

//執行自己的業務,上面的代碼, 爲了保證不重複執行。
echo "run";
sleep(10);

5、php_sapi_name函數 運行模式檢查,判斷是否是 cli執行,爲了避免腳本亂用,cli代碼不能跑在php-fpm模式下,

<?php
// 當然也可以用 PHP_SAPI 判斷
if (php_sapi_name() != "cli") {
   exit("only run in cli \n");
}

6、判斷當前系統是否滿足你的代碼要求,如果只能是linux執行,可以使用常量 PHP_OS或者是DIRECTORY_SEPARATOR

<?php
if (DIRECTORY_SEPARATOR === '\\') {
    exit('only run Unix-like');
}

7、register_argc_argv 設置被設置爲true,所以我們可以使用 $argv $argc 變量,來獲取外部提交的參數個數和值。

<?php
function test(){
  global $argc,$argv;
  echo $argc."\n";
  print_r($argv);
}

test();

執行命令:

php demo4.php hehe haha

結果如下:

8、當然還有個函數 getopt 也是可以用來獲取參數,可以獲取 -a --h 這些命令行參數的

<?php

$options="a:";
$longopts=["help:"];
 
$result= getopt($options,$longopts);

var_dump($result);

執行的時候,就可以使用參數:

php demo5.php -a test --help long

結果如下:

9、cli模式下,php幫我們定義了三個常量: STDIN 、STDOUT、STDERR 用來做標準輸入、標準輸出、標準錯誤,我們打印下,其實就是三個資源句柄:

<?php
var_dump(STDIN,STDOUT,STDERR);

我們可以使用STDIN來接收客戶端的輸入,例如:

<?php
$res1= trim(fgets(STDIN));
$res2= trim(fgets(STDIN));
echo $res1,$res2,"\n";

執行:  

php demo7.php

然後可以輸入兩個值,以換行回車區分

使用STDOUT 和STDERR來輸出標準輸出和標準錯誤:

<?php

 fwrite(STDOUT,"標準輸出\n");
 fwrite(STDERR,"標準錯誤\n");

用於標準輸出和標準錯誤都是輸出到終端的,我們可以使用重定向,將他們重定向到別的地方:

php demo8.php 1>>out 2>>err

例如上面的例子,就是將標準輸出重定向到文件out,將標準錯誤重定向到文件err。

10、查看擴展模塊是否存在可以使用php -m |grep "name" 的方式處理。

php -m|grep pcntl

11、查看php的配置文件,可以使用 php --ini 的方式查找

 

可以看到我的環境配置文件存放於:

/usr/local/php/etc/php-cli.ini 

在php的配置目錄中,我們可以設置兩個php.ini文件,一個是 php.ini ,一個是 php-cli.ini ,一個對應web的php-fpm、一個是對應cli模式的配置,這樣兩者區分開來,web模式下的php.ini,我們可以配置禁用掉一些不怎麼需要,有可能導致安全問題的函數或者類。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章