Skip to content
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待
虚位以待

Laravel Envoy

简介

Laravel Envoy 是一款用于在远程服务器上执行常见任务的工具。使用 Blade 风格的语法,你可以轻松地为部署、Artisan 命令等设置任务。目前,Envoy 仅支持 Mac 和 Linux 操作系统。不过,通过使用 WSL2 也可以实现 Windows 支持。

安装

首先,使用 Composer 包管理器将 Envoy 安装到你的项目中:

shell
composer require laravel/envoy --dev

安装完成后,Envoy 二进制文件将位于你应用程序的 vendor/bin 目录中:

shell
php vendor/bin/envoy

编写任务

定义任务

任务是 Envoy 的基本构建块。任务定义了在调用任务时应在远程服务器上执行的 shell 命令。例如,你可以定义一个任务,该任务在应用程序的所有队列工作服务器上执行 php artisan queue:restart 命令。

你所有的 Envoy 任务都应定义在应用程序根目录下的 Envoy.blade.php 文件中。以下是一个帮助你入门的示例:

blade
@servers(['web' => ['user@192.168.1.1'], 'workers' => ['user@192.168.1.2']])

@task('restart-queues', ['on' => 'workers'])
    cd /home/user/example.com
    php artisan queue:restart
@endtask

如你所见,文件顶部定义了一个 @servers 数组,允许你在任务声明的 on 选项中引用这些服务器。@servers 声明应始终放在单行内。在 @task 声明中,你应放置调用任务时应在服务器上执行的 shell 命令。

本地任务

你可以通过将服务器的 IP 地址指定为 127.0.0.1 来强制脚本在本地计算机上运行:

blade
@servers(['localhost' => '127.0.0.1'])

导入 Envoy 任务

使用 @import 指令,你可以导入其他 Envoy 文件,以便将其故事和任务添加到你的文件中。导入文件后,你可以执行它们包含的任务,就像它们在你自己的 Envoy 文件中定义一样:

blade
@import('vendor/package/Envoy.blade.php')

多台服务器

Envoy 允许你轻松地在多台服务器上运行任务。首先,将其他服务器添加到你的 @servers 声明中。每台服务器应被分配一个唯一的名称。定义好其他服务器后,你可以在任务的 on 数组中列出每台服务器:

blade
@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2']])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate --force
@endtask

并行执行

默认情况下,任务将在每台服务器上串行执行。换句话说,一个任务将在第一台服务器上运行完成后,才会在第二台服务器上执行。如果你希望在多台服务器上并行运行任务,请将 parallel 选项添加到你的任务声明中:

blade
@servers(['web-1' => '192.168.1.1', 'web-2' => '192.168.1.2'])

@task('deploy', ['on' => ['web-1', 'web-2'], 'parallel' => true])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate --force
@endtask

初始化

有时,你可能需要在运行 Envoy 任务之前执行任意的 PHP 代码。你可以使用 @setup 指令来定义一个应在任务之前执行的 PHP 代码块:

php
@setup
    $now = new DateTime;
@endsetup

如果你需要在任务执行之前引入其他 PHP 文件,可以在你的 Envoy.blade.php 文件顶部使用 @include 指令:

blade
@include('vendor/autoload.php')

@task('restart-queues')
    # ...
@endtask

变量

如果需要,你可以在调用 Envoy 时通过在命令行上指定参数来将参数传递给 Envoy 任务:

shell
php vendor/bin/envoy run deploy --branch=master

你可以使用 Blade 的“echo”语法在任务中访问这些选项。你也可以在任务中定义 Blade 的 if 语句和循环。例如,在执行 git pull 命令之前验证 $branch 变量的存在:

blade
@servers(['web' => ['user@192.168.1.1']])

@task('deploy', ['on' => 'web'])
    cd /home/user/example.com

    @if ($branch)
        git pull origin {{ $branch }}
    @endif

    php artisan migrate --force
@endtask

故事

故事将一组任务分组到一个方便的名称下。例如,一个 deploy 故事可以通过在其定义中列出任务名称来运行 update-codeinstall-dependencies 任务:

blade
@servers(['web' => ['user@192.168.1.1']])

@story('deploy')
    update-code
    install-dependencies
@endstory

@task('update-code')
    cd /home/user/example.com
    git pull origin master
@endtask

@task('install-dependencies')
    cd /home/user/example.com
    composer install
@endtask

故事编写完成后,你可以像调用任务一样调用它:

shell
php vendor/bin/envoy run deploy

钩子

当任务和故事运行时,会执行许多钩子。Envoy 支持的钩子类型有 @before@after@error@success@finished。这些钩子中的所有代码都被解释为 PHP 并在本地执行,而不是在你的任务交互的远程服务器上执行。

你可以根据需要定义任意多个这些钩子。它们将按照它们在 Envoy 脚本中出现的顺序执行。

@before

在每次任务执行之前,你 Envoy 脚本中注册的所有 @before 钩子都将执行。@before 钩子接收将要执行的任务的名称:

blade
@before
    if ($task === 'deploy') {
        // ...
    }
@endbefore

@after

在每次任务执行之后,你 Envoy 脚本中注册的所有 @after 钩子都将执行。@after 钩子接收已执行的任务的名称:

blade
@after
    if ($task === 'deploy') {
        // ...
    }
@endafter

@error

在每次任务失败后(退出状态码大于 0),你 Envoy 脚本中注册的所有 @error 钩子都将执行。@error 钩子接收已执行的任务的名称:

blade
@error
    if ($task === 'deploy') {
        // ...
    }
@enderror

@success

如果所有任务都已无错误地执行完毕,你 Envoy 脚本中注册的所有 @success 钩子都将执行:

blade
@success
    // ...
@endsuccess

@finished

在所有任务执行完毕后(无论退出状态如何),所有 @finished 钩子都将执行。@finished 钩子接收已完成任务的状态码,该状态码可能是 null 或一个大于等于 0integer

blade
@finished
    if ($exitCode > 0) {
        // 其中一个任务出现错误...
    }
@endfinished

运行任务

要运行应用程序 Envoy.blade.php 文件中定义的任务或故事,请执行 Envoy 的 run 命令,并传递你想要执行的任务或故事的名称。Envoy 将执行任务并在任务运行时显示远程服务器的输出:

shell
php vendor/bin/envoy run deploy

确认任务执行

如果你希望在服务器上运行给定任务之前提示确认,应在任务声明中添加 confirm 指令。此选项对于破坏性操作特别有用:

blade
@task('deploy', ['on' => 'web', 'confirm' => true])
    cd /home/user/example.com
    git pull origin {{ $branch }}
    php artisan migrate
@endtask

通知

Slack

Envoy 支持在每个任务执行后向 Slack 发送通知。@slack 指令接受一个 Slack 钩子 URL 和一个频道/用户名。你可以在 Slack 控制面板中创建一个“传入 Webhook”集成来获取你的 Webhook URL。

你应该将完整的 Webhook URL 作为第一个参数传递给 @slack 指令。传递给 @slack 指令的第二个参数应为频道名称(#channel)或用户名(@user):

blade
@finished
    @slack('webhook-url', '#bots')
@endfinished

默认情况下,Envoy 通知将向通知频道发送一条描述已执行任务的消息。但是,你可以通过向 @slack 指令传递第三个参数来自定义此消息:

blade
@finished
    @slack('webhook-url', '#bots', 'Hello, Slack.')
@endfinished

Discord

Envoy 还支持在每个任务执行后向 Discord 发送通知。@discord 指令接受一个 Discord 钩子 URL 和一条消息。你可以通过在服务器设置中创建一个“Webhook”并选择该 Webhook 应发布的频道来获取你的 Webhook URL。你应该将完整的 Webhook URL 传递给 @discord 指令:

blade
@finished
    @discord('discord-webhook-url')
@endfinished

Telegram

Envoy 还支持在每个任务执行后向 Telegram 发送通知。@telegram 指令接受一个 Telegram Bot ID 和一个聊天 ID。你可以通过使用 BotFather 创建一个新的机器人来获取你的 Bot ID。你可以使用 @username_to_id_bot 获取一个有效的聊天 ID。你应该将完整的 Bot ID 和聊天 ID 传递给 @telegram 指令:

blade
@finished
    @telegram('bot-id','chat-id')
@endfinished

Microsoft Teams

Envoy 还支持在每个任务执行后向 Microsoft Teams 发送通知。@microsoftTeams 指令接受一个 Teams Webhook(必需)、一条消息、主题颜色(success、info、warning、error)和一个选项数组。你可以通过创建一个新的传入 webhook 来获取你的 Teams Webhook。Teams API 还有许多其他属性可以自定义你的消息框,例如标题、摘要和分区。你可以在 Microsoft Teams 文档中找到更多信息。你应该将完整的 Webhook URL 传递给 @microsoftTeams 指令:

blade
@finished
    @microsoftTeams('webhook-url')
@endfinished