命令行

框架的命令行工具基于 Symfony Console(symfony/console ^6.3)构建,入口为项目根目录的 viswoole 文件,提供服务控制、服务与命令发现、资源发布及门面优化等内置命令,并支持基于 #[AsCommand] 属性的自定义命令扩展。本篇为参考手册,逐一列出全部内置命令的参数与选项。

基本用法

bash
php viswoole list               # 查看全部可用命令
php viswoole help server:start  # 查看指定命令的帮助

命令按三个来源合并加载:框架内置命令 → config/app.phpcommands[]vendor/commands.php(依赖包命令注册文件,由 command:discover 生成)。

内置命令总览

命令说明
server:start启动服务,支持指定服务名、强制启动与守护进程模式
server:close关闭运行中的服务
server:reload重载 Worker 进程,或强制重启整个服务
service:discover扫描依赖包服务提供者,生成 vendor/services.php
command:discover扫描依赖包命令,生成 vendor/commands.php
vendor:publish发布依赖包声明的配置资源到项目根目录
optimize:facade为门面类生成 IDE Helper 注释

路由缓存命令

router:clear-cache 由默认服务 RouterService 在启动时注册,用于清空路由缓存,见 路由配置

服务控制命令

server:start —— 启动服务

bash
php viswoole server:start              # 启动默认服务(http)
php viswoole server:start websocket    # 启动指定服务
php viswoole server:start -d           # 以守护进程方式运行
php viswoole server:start -f           # 服务运行中时,先关闭旧进程再启动
参数/选项类型默认值说明
service(参数)stringserver.default_start_server 的值,即 http要启动的服务名,对应 config/server.phpservers 键名
-f, --force开关关闭强制启动:服务已在运行时向旧主进程发送 SIGINT 信号(最多等待 5 秒),关闭成功后重新启动
-d, --daemonize开关关闭以守护进程(Daemon)方式运行

服务已在运行且未指定 --force 时,命令会抛出「服务正在运行中,请勿重复启动」的异常并以失败状态退出。

server:close —— 关闭服务

bash
php viswoole server:close              # 关闭默认服务
php viswoole server:close websocket    # 关闭指定服务
参数/选项类型默认值说明
server(参数)stringserver.default_start_server 的值,即 http要关闭的服务名

命令向服务主进程发送 SIGINT 信号,触发框架的关闭钩子链路(beforeshutdownshutdown)安全释放资源,见 生命周期钩子

server:reload —— 重载服务

bash
php viswoole server:reload             # 平滑重载 Worker 进程
php viswoole server:reload -t          # 仅重载 Task Worker 进程
php viswoole server:reload -f          # 强制重启整个服务
php viswoole server:reload --force -d  # 强制重启并以守护进程运行
参数/选项类型默认值说明
service(参数)stringserver.default_start_server 的值,即 http服务名
-t, --task开关关闭仅重启 Task Worker 进程(向主进程发送 SIGUSR2 信号)
-f, --force开关关闭强制重启:关闭所有服务进程后重新启动整个服务,会短暂中断服务
-d, --daemonize开关关闭配合 --force 使用,重启后以守护进程运行

默认(不带 --force)的重载通过信号重启 Worker 进程,用于让业务代码变更生效。框架没有独立的 restart 命令,需要完全重启时使用 server:reload --force,或组合 server:close + server:start

reload 不能使所有变更生效

平滑重载从管理进程重新拉起 Worker,服务提供者、全局配置等启动阶段加载的内容不会重新执行,修改这些内容请使用完整重启(server:close + server:start),详见 服务提供者

开发热重载 —— watch 脚本

项目根目录自带 watch 脚本(无额外依赖,基于 find 轮询实现),监控 .php.env 文件变化并自动完整重启服务。由于走的是 server:close + server:start 完整重启,服务提供者、配置等启动阶段内容的变更也能生效,没有平滑重载的局限。

bash
# 首次使用先赋予执行权限(模板项目默认无执行权限)
chmod +x watch

./watch            # 监控文件变化并自动重启服务
./watch -d         # 参数透传给 server:start,以守护进程方式启动

脚本行为:

  1. 启动时先完整启动一次服务,然后进入轮询监控
  2. 每 1 秒扫描一次工作目录(排除 runtimevendor.idea.vscode.git),发现 .php / .env 文件变更后打印变更文件列表
  3. 变更经 1 秒防抖后执行 server:close + server:start 完整重启——连续保存多个文件只触发一次重启
  4. Ctrl+C 退出时自动清理:取消待执行的重启任务并停止服务

脚本顶部的常量可按需调整:

常量默认值说明
WATCH_EXT.php|.env监听的文件后缀,多个用 | 分隔
EXCLUDE_DIRSruntime|vendor|.idea|.vscode|.git排除的目录,多个用 | 分隔
DEBOUNCE_INTERVAL1(秒)防抖间隔,连续变更只触发一次重启
POLL_INTERVAL1(秒)轮询间隔,越小响应越快但 CPU 占用越高

仅限开发环境

watch 脚本以前台进程方式运行,且每次变更都会完整重启服务(中断当前请求),不要用于生产环境。生产部署见 生产环境配置

为什么修改代码必须重启

Viswoole 是常驻内存框架,代码在 Worker 进程启动时载入内存,修改文件后不会自动生效,必须重启进程。原理见 协程与常驻内存

发现与发布命令

service:discover —— 服务发现

bash
php viswoole service:discover

读取 vendor/composer/installed.json,扫描各依赖包 composer.jsonextra.viswoole.services 字段声明的服务提供者类,生成项目根目录的 vendor/services.php。该文件在应用启动时自动加载合并,机制详见 服务提供者

command:discover —— 命令发现

bash
php viswoole command:discover

读取 vendor/composer/installed.json,扫描各依赖包 extra.viswoole.commands 字段声明的命令类,生成项目根目录的 vendor/commands.php 注册文件,框架加载命令行时自动合并。安装或更新依赖包后需重新执行。

vendor:publish —— 发布依赖包资源

bash
php viswoole vendor:publish          # 已存在的目标文件默认跳过
php viswoole vendor:publish -f       # 强制覆盖(--force)
参数/选项类型默认值说明
-f, --force开关关闭覆盖已存在的目标文件

读取 vendor/composer/installed.json,扫描各依赖包 extra.viswoole.configs 字段声明的文件或目录,按原目录层级复制到项目根目录。框架自身的默认配置目录(config/)即通过该字段声明,新项目执行一次即可得到全部默认配置文件,见 配置文件

优化命令

optimize:facade —— 生成门面 IDE Helper

bash
php viswoole optimize:facade "Viswoole\Core\Facade\Task"
php viswoole optimize:facade "Viswoole\Cache\Facade\Cache"
参数/选项类型默认值说明
namespace(参数)string必填需要优化的门面类的完全限定名称

命令通过反射读取门面 getMappingClass() 返回的映射类的全部公共方法(过滤魔术方法),整理为 @method static 注释写入门面类文件,为 IDE 提供静态方法提示。框架内置门面已预生成注释;当你编写自定义门面时(见 门面),执行一次即可生成相同风格的注释。命令会直接修改门面源文件,执行后请检查文件改动。

自定义命令

创建命令类

继承 Symfony Console 的 Command 基类,用 #[AsCommand] 属性声明命令名称与描述:

php
namespace App\Console;

use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

#[AsCommand(
  name        : 'user:create',
  description : '创建新用户',
)]
class UserCreateCommand extends Command
{
  /**
   * 定义参数与选项
   */
  protected function configure(): void
  {
    $this
      // 必填参数:php viswoole user:create 张三
      ->addArgument('name', InputArgument::REQUIRED, '用户名')
      // 可选参数(带默认值)
      ->addArgument('role', InputArgument::OPTIONAL, '角色', 'user')
      // 带值选项:--password=xxx
      ->addOption('password', 'p', InputOption::VALUE_OPTIONAL, '初始密码')
      // 开关选项:--send-email
      ->addOption('send-email', null, InputOption::VALUE_NONE, '发送欢迎邮件');
  }

  /**
   * 执行命令,返回状态码
   */
  protected function execute(InputInterface $input, OutputInterface $output): int
  {
    $io   = new SymfonyStyle($input, $output);
    $name = $input->getArgument('name');
    $role = $input->getOption('role');
    $password = $input->getOption('password') ?? bin2hex(random_bytes(8));

    // ...业务逻辑(命令类经容器创建,可通过构造函数注入服务)

    $io->success("用户创建成功:{$name}({$role})");
    $io->text("<comment>初始密码: {$password}</comment>");
    return Command::SUCCESS;
  }
}

execute() 的返回状态码使用 Command 常量:Command::SUCCESS(0,成功)、Command::FAILURE(1,一般性失败)、Command::INVALID(2,参数无效)。

注册命令

方式一:配置注册。在 config/app.phpcommands[] 中追加命令类:

php
// config/app.php
return [
  // ...其他配置
  'commands' => [
    \App\Console\UserCreateCommand::class,
  ],
];

方式二:依赖包自动发现。扩展包在 composer.json 中声明后,由项目侧执行发现命令生成注册文件:

json
{
  "extra": {
    "viswoole": {
      "commands": ["\Vendor\Package\Console\SyncCommand"]
    }
  }
}
bash
php viswoole command:discover

命令类支持依赖注入

命令类在注册时经容器 invoke() 创建,构造函数可以类型注入已注册的服务(如日志、缓存管理器),与控制器注入机制一致,见 容器

输出与交互

execute() 中推荐使用 SymfonyStyle(Symfony Console 提供)进行格式化输出与交互:

方法用途
success() / error() / warning() / info()带颜色的状态提示
text() / listing() / table()普通文本、列表、表格输出
progressStart() / progressAdvance() / progressFinish()进度条
confirm() / ask() / askHidden() / choice()确认、文本、密码、选择等交互式输入
php
$io = new SymfonyStyle($input, $output);

// 表格输出
$io->table(
  ['ID', '姓名'],
  [[1, '张三'], [2, '李四']]
);

// 交互确认,取消时以无效状态退出
if (!$io->confirm('确定要删除吗?', false)) {
  $io->warning('操作已取消');
  return Command::INVALID;
}

命令调度(定时任务)

框架未内置命令调度器。需要定时执行命令时,可借助系统 crontab 或 Swoole 定时器自行编排,例如每天 0 点重载 Task Worker:

bash
0 0 * * * cd /path/to/project && php viswoole server:reload -t

相关阅读

  • 服务提供者service:discovervendor:publish 背后的服务与资源发现机制
  • 部署:守护进程、Supervisor 与容器环境下的服务管理实践
  • 门面optimize:facade 处理的门面映射机制