命令行
框架的命令行工具基于 Symfony Console(symfony/console ^6.3)构建,入口为项目根目录的 viswoole 文件,提供服务控制、服务与命令发现、资源发布及门面优化等内置命令,并支持基于 #[AsCommand] 属性的自定义命令扩展。本篇为参考手册,逐一列出全部内置命令的参数与选项。
基本用法
php viswoole list # 查看全部可用命令
php viswoole help server:start # 查看指定命令的帮助命令按三个来源合并加载:框架内置命令 → config/app.php 的 commands[] → 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 —— 启动服务
php viswoole server:start # 启动默认服务(http)
php viswoole server:start websocket # 启动指定服务
php viswoole server:start -d # 以守护进程方式运行
php viswoole server:start -f # 服务运行中时,先关闭旧进程再启动| 参数/选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
service(参数) | string | server.default_start_server 的值,即 http | 要启动的服务名,对应 config/server.php 的 servers 键名 |
-f, --force | 开关 | 关闭 | 强制启动:服务已在运行时向旧主进程发送 SIGINT 信号(最多等待 5 秒),关闭成功后重新启动 |
-d, --daemonize | 开关 | 关闭 | 以守护进程(Daemon)方式运行 |
服务已在运行且未指定 --force 时,命令会抛出「服务正在运行中,请勿重复启动」的异常并以失败状态退出。
server:close —— 关闭服务
php viswoole server:close # 关闭默认服务
php viswoole server:close websocket # 关闭指定服务| 参数/选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
server(参数) | string | server.default_start_server 的值,即 http | 要关闭的服务名 |
命令向服务主进程发送 SIGINT 信号,触发框架的关闭钩子链路(beforeshutdown → shutdown)安全释放资源,见 生命周期钩子。
server:reload —— 重载服务
php viswoole server:reload # 平滑重载 Worker 进程
php viswoole server:reload -t # 仅重载 Task Worker 进程
php viswoole server:reload -f # 强制重启整个服务
php viswoole server:reload --force -d # 强制重启并以守护进程运行| 参数/选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
service(参数) | string | server.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 完整重启,服务提供者、配置等启动阶段内容的变更也能生效,没有平滑重载的局限。
# 首次使用先赋予执行权限(模板项目默认无执行权限)
chmod +x watch
./watch # 监控文件变化并自动重启服务
./watch -d # 参数透传给 server:start,以守护进程方式启动脚本行为:
- 启动时先完整启动一次服务,然后进入轮询监控
- 每 1 秒扫描一次工作目录(排除
runtime、vendor、.idea、.vscode、.git),发现.php/.env文件变更后打印变更文件列表 - 变更经 1 秒防抖后执行
server:close+server:start完整重启——连续保存多个文件只触发一次重启 Ctrl+C退出时自动清理:取消待执行的重启任务并停止服务
脚本顶部的常量可按需调整:
| 常量 | 默认值 | 说明 |
|---|---|---|
WATCH_EXT | .php|.env | 监听的文件后缀,多个用 | 分隔 |
EXCLUDE_DIRS | runtime|vendor|.idea|.vscode|.git | 排除的目录,多个用 | 分隔 |
DEBOUNCE_INTERVAL | 1(秒) | 防抖间隔,连续变更只触发一次重启 |
POLL_INTERVAL | 1(秒) | 轮询间隔,越小响应越快但 CPU 占用越高 |
仅限开发环境
watch 脚本以前台进程方式运行,且每次变更都会完整重启服务(中断当前请求),不要用于生产环境。生产部署见 生产环境配置。
为什么修改代码必须重启
Viswoole 是常驻内存框架,代码在 Worker 进程启动时载入内存,修改文件后不会自动生效,必须重启进程。原理见 协程与常驻内存。
发现与发布命令
service:discover —— 服务发现
php viswoole service:discover读取 vendor/composer/installed.json,扫描各依赖包 composer.json 中 extra.viswoole.services 字段声明的服务提供者类,生成项目根目录的 vendor/services.php。该文件在应用启动时自动加载合并,机制详见 服务提供者。
command:discover —— 命令发现
php viswoole command:discover读取 vendor/composer/installed.json,扫描各依赖包 extra.viswoole.commands 字段声明的命令类,生成项目根目录的 vendor/commands.php 注册文件,框架加载命令行时自动合并。安装或更新依赖包后需重新执行。
vendor:publish —— 发布依赖包资源
php viswoole vendor:publish # 已存在的目标文件默认跳过
php viswoole vendor:publish -f # 强制覆盖(--force)| 参数/选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
-f, --force | 开关 | 关闭 | 覆盖已存在的目标文件 |
读取 vendor/composer/installed.json,扫描各依赖包 extra.viswoole.configs 字段声明的文件或目录,按原目录层级复制到项目根目录。框架自身的默认配置目录(config/)即通过该字段声明,新项目执行一次即可得到全部默认配置文件,见 配置文件。
优化命令
optimize:facade —— 生成门面 IDE Helper
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] 属性声明命令名称与描述:
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.php 的 commands[] 中追加命令类:
// config/app.php
return [
// ...其他配置
'commands' => [
\App\Console\UserCreateCommand::class,
],
];方式二:依赖包自动发现。扩展包在 composer.json 中声明后,由项目侧执行发现命令生成注册文件:
{
"extra": {
"viswoole": {
"commands": ["\Vendor\Package\Console\SyncCommand"]
}
}
}php viswoole command:discover命令类支持依赖注入
命令类在注册时经容器 invoke() 创建,构造函数可以类型注入已注册的服务(如日志、缓存管理器),与控制器注入机制一致,见 容器。
输出与交互
execute() 中推荐使用 SymfonyStyle(Symfony Console 提供)进行格式化输出与交互:
| 方法 | 用途 |
|---|---|
success() / error() / warning() / info() | 带颜色的状态提示 |
text() / listing() / table() | 普通文本、列表、表格输出 |
progressStart() / progressAdvance() / progressFinish() | 进度条 |
confirm() / ask() / askHidden() / choice() | 确认、文本、密码、选择等交互式输入 |
$io = new SymfonyStyle($input, $output);
// 表格输出
$io->table(
['ID', '姓名'],
[[1, '张三'], [2, '李四']]
);
// 交互确认,取消时以无效状态退出
if (!$io->confirm('确定要删除吗?', false)) {
$io->warning('操作已取消');
return Command::INVALID;
}命令调度(定时任务)
框架未内置命令调度器。需要定时执行命令时,可借助系统 crontab 或 Swoole 定时器自行编排,例如每天 0 点重载 Task Worker:
0 0 * * * cd /path/to/project && php viswoole server:reload -t