Skip to content

命令行(CLI)开发指南

PHP 不只是用于 Web,CLI 模式下可以编写强大的命令行工具。

基础用法

php
#!/usr/bin/env php
<?php
// hello.php - 第一行是 Shebang(Linux/Mac)
echo "Hello, World!\n";

运行:

bash
php hello.php
# 或添加执行权限后
chmod +x hello.php
./hello.php

接收参数

php
<?php
// script.php
// $argv 是参数数组,$argc 是参数个数
print_r($argv);

echo "脚本名: " . $argv[0] . "\n";
echo "第一个参数: " . ($argv[1] ?? '无') . "\n";

// 使用 getopt 解析选项
$options = getopt("n:a::v", ["name:", "age::", "verbose"]);
// -n 或 --name 是必填值
// -a 或 --age 是可选值
// -v 或 --verbose 是开关
// 使用: php script.php -n 张三 -a 25 -v

交互式输入输出

php
<?php
// 提示用户输入
echo "请输入姓名: ";
$name = trim(fgets(STDIN));
echo "你好, $name!\n";

// 密码输入(无回显)
echo "请输入密码: ";
system('stty -echo');  // 关闭回显
$password = trim(fgets(STDIN));
system('stty echo');   // 恢复回显
echo "\n密码长度: " . strlen($password) . "\n";

// 带颜色的输出
function color($text, $color) {
    $colors = [
        'red'    => "\033[31m",
        'green'  => "\033[32m",
        'yellow' => "\033[33m",
        'reset'  => "\033[0m"
    ];
    return $colors[$color] . $text . $colors['reset'];
}

echo color("成功!\n", 'green');
echo color("警告!\n", 'yellow');
echo color("错误!\n", 'red');

进度条实现

php
<?php
function progressBar($done, $total, $width = 50) {
    $percent = $done / $total;
    $bar = floor($percent * $width);
    
    $status = sprintf("[%s>%s] %d%% %d/%d",
        str_repeat("=", $bar),
        str_repeat(" ", $width - $bar),
        round($percent * 100),
        $done,
        $total
    );
    
    echo "\r$status";
    flush();
}

// 使用示例
$total = 100;
for ($i = 0; $i <= $total; $i++) {
    progressBar($i, $total);
    usleep(50000);  // 模拟工作
}
echo "\n完成!\n";

守护进程基础

php
<?php
// 创建守护进程
function daemonize() {
    // 1. Fork 子进程
    $pid = pcntl_fork();
    if ($pid == -1) {
        die("无法 fork");
    } elseif ($pid > 0) {
        exit(0);  // 父进程退出
    }
    
    // 2. 创建新会话
    posix_setsid();
    
    // 3. 改变工作目录
    chdir('/');
    
    // 4. 关闭文件描述符
    fclose(STDIN);
    fclose(STDOUT);
    fclose(STDERR);
}

// 信号处理
pcntl_signal(SIGTERM, function() {
    echo "收到终止信号,正在退出...\n";
    exit(0);
});

// 主循环
while (true) {
    pcntl_signal_dispatch();  // 处理信号
    // 执行定时任务
    sleep(1);
}

常用 CLI 函数

php
<?php
// 检查是否在 CLI 模式
if (php_sapi_name() !== 'cli') {
    exit('只能在命令行运行');
}

// 获取当前用户
$user = posix_getpwuid(posix_getuid())['name'];

// 获取内存使用
echo memory_get_usage(true) / 1024 / 1024 . " MB\n";
echo memory_get_peak_usage(true) / 1024 / 1024 . " MB\n";

// 执行系统命令
$output = shell_exec('ls -la');
$lastLine = exec('pwd');
passthru('git status');  // 直接输出到终端

// 退出状态码
exit(0);  // 成功
exit(1);  // 一般错误
exit(2);  // 误用命令

注意事项

  1. CLI 模式下没有超时限制(max_execution_time = 0)
  2. 没有 $_GET, $_POST 等超全局变量
  3. 错误会直接输出到终端(除非重定向)
  4. 脚本执行权限要正确设置

Binstork