游侠网云服务,免实名免备案服务器 游侠云域名,免实名免备案域名

统一声明:

1.本站联系方式
QQ:709466365
TG:@UXWNET
官方TG频道:@UXW_NET
如果有其他人通过本站链接联系您导致被骗,本站一律不负责!

2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET
3.免实名域名注册购买- 游侠云域名
4.免实名国外服务器购买- 游侠网云服务
PHP-CLI命令行模式开发从新手到高手:实战教程+进阶技巧全攻略

这篇全攻略专为新手到高手的成长路径设计:从最基础的环境搭建、常用指令(比如php -v查版本、php -f运行脚本)、参数传递(位置参数、长/短选项)讲起,用“一步一操作”帮你打通入门关;接着通过真实场景实战——比如写一个批量导出数据库的脚本、做一个定时清理日志的定时任务,教你把CLI用在实际工作中;最后深入进阶技巧:如何优化脚本性能(比如减少内存占用)、如何捕获致命错误、如何规范日志管理,帮你写出稳定可靠的CLI程序。

不管你是想解决“重复劳动”的痛点,还是想补全PHP全栈能力,这篇文章都能带你从“怕碰命令行”到“熟练写CLI工具”。每部分都有具体例子和避坑指南,看完就能动手实践,真正把PHP-CLI变成提升效率的“利器”。

你有没有过这种情况?做PHP Web开发时写接口、调框架都顺风顺水,可一旦要写个命令行脚本——比如批量导数据、定时清日志,立刻就慌了:明明语法熟,却不知道怎么在终端运行;传个参数要么收不到要么格式错;脚本跑着跑着突然崩了,连错在哪都找不到?其实我刚接触PHP-CLI时也这样,第一次帮朋友写清理日志的脚本,没配环境变量,Windows下打开cmd输php直接提示“不是内部命令”,折腾了半小时才搞定;后来写参数传递,用$_GET居然没反应,查了PHP官方文档才知道CLI模式没有HTTP请求,得用$_SERVER['argv'](引用自PHP官方CLI文档:https://www.php.net/manual/zh/features.commandline.phpnofollow)。今天这篇全攻略,就是把我从新手到能独立写CLI工具的经验揉碎了讲,不管你是刚碰命令行的小白,还是想补全技能的PHP开发者,跟着走就能解决80%的CLI问题。

从0到1:PHP-CLI入门必须踩稳的3个台阶

入门CLI的核心不是记多少指令,而是解决“跑不起来”“传不对”“崩了找不到原因”这三个基础问题。我见过很多人一开始就去学复杂的框架,结果基础没打牢,遇到小问题还是卡壳——不如先把这三个台阶踩稳。

  • 环境搭建与基础指令:别让“跑不起来”卡住第一步
  • 很多人入门的第一个坑是“脚本跑不起来”,其实90%的问题出在环境配置指令用错。先讲环境:Windows系统要先把PHP的安装目录加到环境变量里——比如你装在C:php-8.2.0,就把这个路径加到系统变量的Path里,然后打开cmd输php -v,能看到版本号(比如PHP 8.2.0 (cli))就对了;Linux系统一般默认装了PHP,但可能版本旧,比如Ubuntu可以用apt install php8.2-cli装最新的CLI版本(注意要装cli包,不是apache2fpm包),装完同样输php -v验证。

    接下来是基础指令,这几个是我每天用得最多的:

  • php -v:查PHP版本,确认环境没问题;
  • php -f 脚本路径:运行指定脚本,比如php -f test.php,这是最常用的;
  • php -r "代码":执行单行PHP代码,比如php -r "echo date('Y-m-d');",适合快速测试小功能;
  • php -i:查看PHP的配置信息,比如查有没有装mysqli扩展,输php -i | grep mysqli就能看到。
  • 我之前帮一个刚学PHP的朋友调脚本,他说“我写了个echo 'hello'的脚本,双击没反应”——后来发现他直接双击.php文件,系统用浏览器打开了,其实应该用cmd进脚本目录,输php test.php才对。CLI的本质是“用终端调用PHP解释器执行脚本”,别把Web模式的习惯带过来。

  • 参数传递:别再用$_GET,学会用这两个“神器”
  • Web开发里传参数用$_GET$_POST,但CLI模式没有HTTP请求,参数是通过命令行输入传给脚本的。这里要记两个核心方法:位置参数选项参数

    先讲位置参数,用$_SERVER['argv']获取——比如你写个test.php,里面写print_r($_SERVER['argv']);,然后在终端输php test.php a b c,会输出一个数组:Array([0] => test.php [1] => a [2] => b [3] => c)。第一个元素是脚本路径,后面的是你传的参数。我之前写过一个计算两个数相加的脚本,用$_SERVER['argv'][1]$_SERVER['argv'][2]取参数,比如php add.php 1 2,输出3,简单但实用。

    再讲选项参数,比如你需要传“name 张三 age 20”这种键值对,就得用getopt函数。比如脚本里写:

    $options = getopt('n:a:', ['name:', 'age:']);
    

    print_r($options);

    这里的'n:a:'代表短选项-n(冒号表示必须传值),'name:'是长选项name(同样要传值)。然后你输php test.php -n 张三 age 20$options会输出Array([n] => 张三 [age] => 20)。我之前帮公司写接口测试脚本时,用getopt传接口地址、请求方法、参数,比如php test_api.php url http://example.com/api method POST data '{"id":1}',这样脚本里就能根据这些参数发请求,特别灵活。

  • 错误处理:别让“突然崩了”变成未解之谜
  • CLI脚本不像Web项目有浏览器提示错误,一旦崩了如果没日志,根本不知道哪错了。我之前帮朋友写个读取文件的脚本,没加错误处理,遇到文件不存在直接输出“Warning: file_get_contents(xxx.txt): Failed to open stream: No such file or directory”然后退出,他来找我时说“脚本突然停了,不知道为什么”。后来我帮他加了错误处理函数,把错误写到日志文件里:

    set_error_handler(function($errno, $errstr, $errfile, $errline) {
    

    $log = date('Y-m-d H:i:s') . " 错误级别: $errno 错误信息: $errstr 文件名: $errfile 行号: $errlinen";

    file_put_contents('error.log', $log, FILE_APPEND);

    });

    这样再遇到错误,就能在error.log里看到详细信息(比如“2024-05-20 14:30:00 错误级别: 2 错误信息: file_get_contents(xxx.txt): Failed to open stream: No such file or directory 文件名: test.php 行号: 5”),排查起来特别快。 对于可预知的错误(比如数据库连接失败),可以用try-catch抓异常:

    try {
    

    $pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

    } catch (PDOException $e) {

    echo "数据库连接失败: " . $e->getMessage() . "n";

    exit(1); // 非0退出表示出错,方便定时任务判断结果

    }

    加了这两步,脚本崩了也能快速定位问题——这是我踩过很多坑才 出来的经验。

    实战进阶:用PHP-CLI解决工作中80%的自动化需求

    CLI的核心价值是自动化——把重复的、耗时间的工作交给脚本做,比如每天导出数据、每周清理日志、批量测接口,这些都是我工作中常遇到的场景,用CLI脚本就能省大量时间。

  • 批量导出数据库:从“手动查库”到“自动存CSV”
  • 我之前在电商公司做开发时,运营每天要导出前一天的订单数据,手动用PHPMyAdmin查库、导出,要花10分钟,遇到数据多还容易卡。后来我写了个CLI脚本,每天凌晨2点自动跑,把数据导出到CSV,运营早上来直接拿文件就行。

    脚本的逻辑很简单,但要注意异常处理路径问题

  • 用PDO连接数据库(加异常处理,避免连接失败崩脚本);
  • 写SQL查询前一天的订单:SELECT order_id, user_id, amount, create_time FROM orders WHERE create_time >= CURDATE()
  • INTERVAL 1 DAY
  • 执行查询,获取结果集;
  • 打开CSV文件,写入表头(订单ID、用户ID、金额、创建时间);
  • 循环结果集,把每一行数据写入CSV;
  • 关闭文件和数据库连接。
  • 关键代码比如:

    try {
    

    $pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', 'password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);

    $stmt = $pdo->query("SELECT order_id, user_id, amount, create_time FROM orders WHERE create_time >= CURDATE()

  • INTERVAL 1 DAY");
  • $orders = $stmt->fetchAll(PDO::FETCH_ASSOC);

    // 生成CSV文件路径(比如/var/exports/orders_20240520.csv)

    $csvPath = '/var/exports/orders_' . date('Ymd') . '.csv';

    $csvFile = fopen($csvPath, 'w');

    // 写入表头

    fputcsv($csvFile, array_keys($orders[0]));

    // 写入数据

    foreach ($orders as $order) {

    fputcsv($csvFile, $order);

    }

    fclose($csvFile);

    echo "导出成功:$csvPathn";

    } catch (Exception $e) {

    echo "导出失败:" . $e->getMessage() . "n";

    exit(1);

    }

    然后用crontab定时执行:输crontab -e,加一行0 2 php /path/to/export_orders.php(每天凌晨2点跑)。运营后来跟我说,这个脚本帮他们省了每天10分钟,一个月就是5小时,能多做很多事。

  • 定时清理日志:别让“日志占满硬盘”变成运维的噩梦
  • 我之前帮一个做SaaS的朋友处理过服务器问题——他们的应用日志存在/var/log/app里,每天生成1G日志,没清理过,结果硬盘满了导致应用崩了。后来我写了个CLI脚本,每周日凌晨3点自动清理30天前的日志。

    脚本的逻辑更简单,但要注意文件判断(别删错文件):

    $logDir = '/var/log/app';
    

    $expireDays = 30;

    $expireTime = $expireDays 86400; // 30天的秒数

    // 遍历日志目录里的.log文件

    $files = glob($logDir . '/.log');

    foreach ($files as $file) {

    if (is_file($file)) {

    $fileTime = filemtime($file);

    // 如果文件修改时间超过30天,删除

    if (time()

  • $fileTime > $expireTime) {
  • unlink($file);

    echo "Deleted: $filen";

    }

    }

    }

    然后用crontab定时:0 3 0 php /path/to/clean_logs.php(每周日凌晨3点跑)。朋友后来跟我说,服务器硬盘使用率从90%降到了30%,运维再也没找过他麻烦。

  • 接口测试:用CLI脚本替代Postman,批量测接口
  • 做接口开发时,我常要测多个参数组合的情况,比如测用户登录接口,要测“正确账号密码”“错误密码”“空账号”这几种情况,用Postman要手动改参数,麻烦。后来我写了个CLI脚本,用curl扩展发请求,批量测接口,还能生成测试报告。

    脚本的逻辑是定义测试用例→循环发请求→对比结果

    // 定义测试用例
    

    $tests = [

    [

    'name' => '正确账号密码',

    'url' => 'http://example.com/api/login',

    'method' => 'POST',

    'data' => ['username' => 'admin', 'password' => '123456'],

    'expected' => ['code' => 200, 'msg' => '登录成功']

    ],

    [

    'name' => '错误密码',

    'url' => 'http://example.com/api/login',

    'method' => 'POST',

    'data' => ['username' => 'admin', 'password' => 'wrong'],

    'expected' => ['code' => 401, 'msg' => '密码错误']

    ],

    [

    'name' => '空账号',

    'url' => 'http://example.com/api/login',

    'method' => 'POST',

    'data' => ['username' => '', 'password' => '123456'],

    'expected' => ['code' => 400, 'msg' => '账号不能为空']

    ]

    ];

    // 循环测试

    foreach ($tests as $test) {

    echo "测试用例:{$test['name']}...";

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $test['url']);

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // POST请求处理

    if ($test['method'] == 'POST') {

    curl_setopt($ch, CURLOPT_POST, true);

    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($test['data']));

    }

    $response = curl_exec($ch);

    curl_close($ch);

    $result = json_decode($response, true);

    // 对比结果

    if ($result['code'] == $test['expected']['code'] && $result['msg'] == $test['expected']['msg']) {

    echo "通过!n";

    } else {

    echo "失败!响应:" . json_encode($result) . "n";

    }

    }

    跑这个脚本就能一次性测所有用例,比Postman快多了。我之前测一个支付接口,用这个脚本测了10个用例,只用了2分钟,要是用Postman得10分钟。

    附:PHP-CLI常用指令表

    下面是我整理的高频CLI指令,记下来能省很多查文档的时间:


    PHP-CLI脚本跑不起来怎么办?

    先检查环境配置——Windows系统要把PHP安装目录加到环境变量的Path里,比如装在C:php-8.2.0,就把这个路径添进系统变量的Path,然后打开cmd输php -v,能看到版本号(比如PHP 8.2.0 (cli))就对了;Linux系统如果没装CLI包,用apt install php8.2-cli(Ubuntu)装一下,装完同样用php -v验证。

    另外要注意指令用法,运行脚本得用php -f 脚本路径,比如php -f test.php,别直接双击.php文件(那会用浏览器打开,不是CLI模式)。我之前帮朋友调脚本,他双击文件没反应,后来用cmd进脚本目录输指令才跑起来。

    PHP-CLI里怎么传参数?为什么$_GET没用?

    因为PHP-CLI没有HTTP请求,所以Web模式的$_GET、$_POST这些超全局变量用不了,得用位置参数或长/短选项。位置参数用$_SERVER['argv']取,比如php test.php a b$_SERVER['argv'][1]就是a,$_SERVER['argv'][2]就是b;长/短选项用getopt函数,比如要传name和-a,写getopt('a:', ['name:']),然后输php test.php name 张三 -a 20,就能拿到参数数组。

    我之前写接口测试脚本,用getopt传接口地址和请求方法,比如php test_api.php url http://example.com method POST,脚本里直接用这些参数发请求,比Web模式灵活多了。

    用PHP-CLI写批量导出数据库脚本要注意什么?

    首先得加异常处理——用PDO连接数据库时,要设置PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,这样连接失败会抛出异常,不会直接崩脚本;然后处理文件路径,导出的CSV文件要写绝对路径(比如/var/exports/orders_20240520.csv),别用相对路径,避免找不到存储位置。

    还有定时任务配置,Linux用crontab -e加一行0 2 php /path/to/export_orders.php,就能每天凌晨2点自动跑;Windows可以用“任务计划程序”,选好脚本路径和执行时间。我之前帮电商公司写这个脚本,加了这些处理后,运营再也没找过我调导出问题。

    PHP-CLI脚本崩了找不到原因怎么办?

    先加错误日志——用set_error_handler函数把错误信息写到日志文件里,比如把错误级别、信息、文件名和行号存到error.log,这样崩了能直接看日志找问题;然后对可预知的错误(比如数据库连接、文件操作)用try-catch抓异常,比如连接数据库时写try { $pdo = new PDO(...); } catch (PDOException $e) { echo "数据库连接失败: " . $e->getMessage(); exit(1); },非0退出状态码能让定时任务知道脚本出错了。

    我之前帮朋友写清理日志脚本,没加错误处理,遇到文件不存在直接报错退出,后来加了set_error_handler,日志里清楚写着哪个文件没找到,一下就定位到问题了。

    用PHP-CLI写定时清理日志脚本要注意什么?

    首先要判断文件类型——用glob遍历日志目录里的.log文件(比如$files = glob('/var/log/app/.log')),然后用is_file确认是文件再处理,别误删目录;然后计算过期时间,比如清理30天前的日志,用$expireTime = 30 86400(30天的秒数),对比文件修改时间(filemtime($file)),超过就用unlink删除。

    还要注意脚本权限,Linux下要给脚本执行权限(chmod +x clean_logs.php),定时任务用root用户运行,避免没权限删文件。我之前帮做SaaS的朋友写这个脚本,一开始用普通用户跑,删不了日志,后来改成root用户才解决。

    指令 作用 示例
    php -v 查看PHP版本 php -v
    php -f 运行指定PHP脚本 php -f test.php
    php -r 执行单行PHP代码 php -r “echo ‘Hello CLI’;”
    php -i 查看PHP配置信息 php -i | grep mysqli
    php help 查看所有CLI指令帮助 php help