创建命令
除了使用 Ace 命令,您还可以创建自定义命令作为应用程序代码库的一部分。命令存储在 commands 目录(根级别)中。您可以通过运行以下命令创建命令。
另请参阅:Make command
node ace make:command greet上述命令将在 commands 目录中创建一个 greet.ts 文件。Ace 命令由一个类表示,必须实现 run 方法来执行命令指令。
命令元数据
命令元数据包括命令名称、描述、帮助文本和配置命令行为的选项。
import { BaseCommand } from '@adonisjs/core/ace'
import { CommandOptions } from '@adonisjs/core/types/ace'
export default class GreetCommand extends BaseCommand {
static commandName = 'greet'
static description = 'Greet a user by name'
static options: CommandOptions = {
startApp: false,
allowUnknownFlags: false,
staysAlive: false,
}
}- commandName
commandName属性用于定义命令名称。命令名称不应包含空格。此外,建议避免在命令名称中使用不常见的特殊字符,如*、&或斜杠。命令名称可以在命名空间下。例如,要在
make命名空间下定义命令,可以用make:作为前缀。- description
命令描述显示在命令列表和命令帮助屏幕中。您应该保持描述简短,并使用帮助文本进行更长的描述。
- help
帮助文本用于编写更长的描述或显示使用示例。
tsexport default class GreetCommand extends BaseCommand { static help = [ 'The greet command is used to greet a user by name', '', 'You can also send flowers to a user, if they have an updated address', '{{ binaryName }} greet --send-flowers', ] }变量替换是对用于执行 ace 命令的二进制文件的引用。- aliases
您可以使用
aliases属性为命令名称定义一个或多个别名。tsexport default class GreetCommand extends BaseCommand { static commandName = 'greet' static aliases = ['welcome', 'sayhi'] }- options.startApp
默认情况下,AdonisJS 在运行 Ace 命令时不会启动应用程序。这确保命令快速运行,不会经过应用程序启动阶段来执行简单任务。
但是,如果您的命令依赖于应用程序状态,可以告诉 Ace 在执行命令之前启动应用程序。
tsimport { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' export default class GreetCommand extends BaseCommand { // highlight-start static options: CommandOptions = { startApp: true } // highlight-end }- options.allowUnknownFlags
默认情况下,如果您向命令传递未知标志,Ace 会打印错误。但是,您可以使用
options.allowUnknownFlags属性在命令级别禁用严格的标志解析。tsimport { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' export default class GreetCommand extends BaseCommand { // highlight-start static options: CommandOptions = { allowUnknownFlags: true } // highlight-end }- options.staysAlive
AdonisJS 在执行命令的
run命令后会隐式终止应用程序。但是,如果您想在命令中启动长时间运行的进程,必须告诉 Ace 不要终止进程。另请参阅:终止应用程序和在应用程序终止前清理部分。
tsimport { BaseCommand } from '@adonisjs/core/ace' import { CommandOptions } from '@adonisjs/core/types/ace' export default class GreetCommand extends BaseCommand { // highlight-start static options: CommandOptions = { staysAlive: true } // highlight-end }
命令生命周期方法
您可以在命令类上定义以下生命周期方法,Ace 将按预定义的顺序执行它们。
import { BaseCommand, args, flags } from '@adonisjs/core/ace'
export default class GreetCommand extends BaseCommand {
async prepare() {
console.log('preparing')
}
async interact() {
console.log('interacting')
}
async run() {
console.log('running')
}
async completed() {
console.log('completed')
}
}| 方法 | 描述 |
|---|---|
prepare | 这是 Ace 在命令上执行的第一个方法。此方法可以设置运行命令所需的状态或数据。 |
interact | interact 方法在 prepare 方法之后执行。它可用于向用户显示提示。 |
run | 命令的主要逻辑放在 run 方法中。此方法在 interact 方法之后调用。 |
completed | completed 方法在运行所有其他生命周期方法后调用。此方法可用于执行清理或处理/显示其他方法引发的错误。 |
依赖注入
Ace 命令使用 IoC 容器构造和执行。因此,您可以在命令生命周期方法上类型提示依赖项,并使用 @inject 装饰器来解析它们。
为了演示,让我们在所有生命周期方法中注入 UserService 类。
import { inject } from '@adonisjs/core'
import { BaseCommand } from '@adonisjs/core/ace'
import UserService from '#services/user_service'
export default class GreetCommand extends BaseCommand {
@inject()
async prepare(userService: UserService) {
}
@inject()
async interact(userService: UserService) {
}
@inject()
async run(userService: UserService) {
}
@inject()
async completed(userService: UserService) {
}
}处理错误和退出代码
命令引发的异常使用 CLI 日志记录器显示,命令 exitCode 设置为 1(非零错误代码表示命令失败)。
但是,您也可以通过将代码包装在 try/catch 块中或使用 completed 生命周期方法来捕获错误来处理错误。在任何一种情况下,请记住更新命令的 exitCode 和 error 属性。
使用 try/catch 处理错误
import { BaseCommand } from '@adonisjs/core/ace'
export default class GreetCommand extends BaseCommand {
async run() {
try {
await runSomeOperation()
} catch (error) {
this.logger.error(error.message)
this.error = error
this.exitCode = 1
}
}
}在 completed 方法中处理错误
import { BaseCommand } from '@adonisjs/core/ace'
export default class GreetCommand extends BaseCommand {
async run() {
await runSomeOperation()
}
async completed() {
if (this.error) {
this.logger.error(this.error.message)
/**
* 通知 Ace 错误已被处理
*/
return true
}
}
}终止应用程序
默认情况下,Ace 会在执行命令后终止应用程序。但是,如果您启用了 staysAlive 选项,则必须使用 this.terminate 方法显式终止应用程序。
假设我们建立一个 redis 连接来监控服务器内存。我们监听 redis 连接的 error 事件,并在连接失败时终止应用程序。
import { BaseCommand } from '@adonisjs/core/ace'
import { CommandOptions } from '@adonisjs/core/types/ace'
export default class GreetCommand extends BaseCommand {
static options: CommandOptions = {
staysAlive: true
}
async run() {
const redis = createRedisConnection()
// highlight-start
redis.on('error', (error) => {
this.logger.error(error)
this.terminate()
})
// highlight-end
}
}在应用程序终止前清理
多个事件可以触发应用程序终止,包括 SIGTERM 信号。因此,您必须在命令中监听 terminating 钩子以执行清理。
您可以在 prepare 生命周期方法中监听终止钩子。
import { BaseCommand } from '@adonisjs/core/ace'
import { CommandOptions } from '@adonisjs/core/types/ace'
export default class GreetCommand extends BaseCommand {
static options: CommandOptions = {
staysAlive: true
}
prepare() {
this.app.terminating(() => {
// 执行清理
})
}
async run() {
}
}