ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Deployer Selector 完全指南:用标签精确调度主机与任务

Deployer Selector 完全指南:用标签精确调度主机与任务 Deployer Selector 完全指南用标签精确调度主机与任务【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址: https://gitcode.com/gh_mirrors/de/deployer导读Selector选择器是 Deployer 中用于挑选主机来执行任务的机制每台主机携带一组键值对labels标签例如stage: production、role: webSelector 负责根据这些标签过滤出目标主机。无论是命令行传参dep info envprod、任务体内动态筛选select()/on()还是为任务绑定固定选择器-select()都建立在同一套标签匹配语义之上。读完本文你将完整掌握 Deployer Selector 的语法OR/AND/取反/别名、源码级匹配原理以及它在 MAML 配置、任务调度与once语义中的实际应用方式。一、标签LabelsSelector 的匹配基础Selector 不是凭空选主机而是基于主机上的键值对标签进行匹配。标签通过host()定义主机时一并声明host(web.example.com) -setLabels([ type web, env prod, ]); host(db.example.com) -setLabels([ type db, env prod, ]);已存在的主机可用-addLabels()追加/合并标签。其底层实现位于 Host.phpsetLabels()直接写入配置键labels而addLabels()会先取出已有标签再通过array_replace_recursive与新增标签递归合并后回写因此可以安全地分多次、分层地补充标签而不覆盖已有内容host(api.example.com) -setLabels([type api]) -addLabels([env staging, region eu]);labels在内部就是主机配置中的一个数组键。Host::get(labels, [])读取它而Selector::apply()在匹配时同样通过$host-get(labels, [])取出标签集见 Selector.php两者共用同一份数据不存在两套标签源。二、第一个实战用选择器运行任务定义打印标签的任务task(info, function () { writeln(type: . get(labels)[type] . env: . get(labels)[env]); });get(labels)取的是当前主机的标签Context中已切到该主机。不带选择器运行会作用于所有主机带上选择器则只作用于匹配的主机$ dep info envprod task info [web.example.com] type:web env:prod [db.example.com] type:db env:prod两台主机都匹配envprod。进一步收窄条件$ dep info typeweb task info [web.example.com] type:web env:prod命令行选择器由SelectCommand统一处理SelectCommand.php取到的参数数组会用implode(,, ...)拼成单个选择表达式后交给Deployer::get()-selector-select()。若不传任何选择器且配置了default_selector全局配置则使用该默认值交互式终端下还会弹出多选清单让你挑选主机。三、Selector 语法OR、AND、值内 OR 与取反一个选择器是由条件组成的列表条件之间用,OR或AND连接。下面是完整语法均以第一节的两台主机为例。OR,typeweb,envprod匹配typeweb或envprod$ dep info typeweb,envprod task info [web.example.com] type:web env:prod [db.example.com] type:db env:prodANDtypeweb envprod要求同时满足两者$ dep info typeweb envprod task info [web.example.com] type:web env:prod值内 OR|typeweb|db envprod表示(typeweb OR typedb) AND envprod注意运算符优先级——|只在单个值内部生效不会跨越$ dep info typeweb|db envprod task info [web.example.com] type:web env:prod [db.example.com] type:db env:prod取反!type!web排除标签为typeweb的主机$ dep info type!web task info [db.example.com] type:db env:prod关于解析顺序源码给出了精确的层级Selector::parse()先用explode(,)按 OR 切分整个表达式得到若干个子条件组每个子条件组再按explode()切分 AND 部分每个部分trim()后若不含则当作别名条件见下文否则用正则/(?var.?)(?op!?)(?value.)/拆出变量 / 操作符 / 值值部分再按|拆成候选数组。而apply()Selector.php的求值逻辑是同一组条件全部为真则整组命中任一|候选值命中即视为该条件为真组与组之间是 OR任一组命中即匹配。这与直觉完全一致的优先级高于顶层,。:::note多个选择器参数等价于逗号拼接dep info typeweb envprod≡dep info typeweb,envprod。另外bash 自动补全支持选择器提示——参考 installation。 :::四、特殊选择器all与别名匹配all—— 匹配每一台主机。alias...—— 按主机别名匹配。任何不含的 token 都被视作别名见parse()中 else 分支[, alias, trim($part)]因此dep info web.example.com≡dep info aliasweb.example.com$ dep info web.example.com task info [web.example.com] type:web env:prod多别名可并列等价于逗号连接的别名条件$ dep info web.example.com db.example.com $ # Same as: $ dep info aliasweb.example.com,aliasdb.example.com别名与true标签的源码细节在apply()中匹配时实际参与比较的标签集合会额外注入两个隐式标签Selector.php$labels $host-get(labels, []); $labels[alias] $host-getAlias(); // 把主机别名当作可匹配标签 $labels[true] true; // 恒真标签供 all 使用alias标签让alias...和裸 token 生效true标签让all变为等价于[, true, true]的条件从而无条件命中所有主机。compare()支持与!两种操作符要求标签值严格等于候选值比较且支持标签值为数组时逐个元素比对这与值内 OR天然兼容!则取反。当标签缺失时按null参与比较——因此type!web同样会命中没有type标签的主机这一点在编写排除条件时值得留意。五、在 PHP 代码中使用选择器select()与on()除了命令行任务内部也能动态地按选择器取主机。select(expr)返回匹配主机的数组定义见 functions.php实现为Deployer::get()-selector-select($selector)task(info, function () { $hosts select(typeweb|db,envprod); foreach ($hosts as $host) { writeln(type: . $host-get(labels)[type] . env: . $host-get(labels)[env]); } });on(hosts, callback)对每个匹配主机依次执行回调并自动完成Context的压栈/出栈、配置加载与保存functions.phptask(info, function () { on(select(all), function () { writeln(type: . get(labels)[type] . env: . get(labels)[env]); }); });on()的回调里get()/run()都作用于当前遍历到的主机它同样接受单台主机或主机集合甚至可以传Deployer::get()-hosts遍历全部主机。相关完整 API 见 api.md。六、任务级选择器-select()可以把选择器固定绑定到某个任务上这样无论谁调用该任务都只会作用到匹配的主机tasks.md 中的select配置task(info, function () { // ... })-select(typeweb|db,envprod);Task::select()只是把表达式缓存为解析结果Task.php$this-selector Selector::parse($selector);。真正消费它的是执行器 Master.php——在执行每个任务前用Selector::apply($task-getSelector(), $currentHost)逐主机判定未命中的主机直接从本任务的执行计划中剔除。这个机制还与 Deployer 的任务调度特性深度耦合once单次执行只在第一个匹配选择器的主机上运行一次oncePerNode每节点一次按hostname或标签node去重每组节点只跑一次见 Master.php子任务继承脚本中的子任务会通过addSelector()合并父任务的 selectorScriptManager.php保证过滤条件在整个调用链上传递。在并行场景--parallel、--limit下Master 同样在每个分块内先按 selector 过滤再派发Master.php因此任务级选择器在串行与并行模式下行为一致。七、MAML 中的标签MAML 配方同样支持 labels。标签写在主机的labels键下与env环境配置平级{ hosts: { web.example.com: { remote_user: deployer env: { environment: production } labels: { env: prod } } } }不要把env配置键和labels.env标签混为一谈二者相互独立env存放的是 MAML 里定义的部署环境配置labels.env只是参与 selector 匹配的标签值。可以在同一任务里同时读取验证task(info, function () { writeln(env: . get(env)[environment] . labels.env: . get(labels)[env]); });$ dep info envprod task info [web.example.com] env:production labels.env:prod这里命令行选择器匹配的是labels.envprod而打印出的env:production来自配置键env——两者互不干扰。八、命令行交互细节与调试几个有助于日常使用的命令行行为默认选择器全局配置default_selector可在不传参时生效SelectCommand.php交互式选择配置了多台主机且未给选择器时终端会弹出多选清单ChoiceQuestion支持逗号分隔多选无命中即报错表达式写错或没有主机匹配时命令会抛出异常并回显选择器原文便于排查SelectCommand.phpShell 自动补全selector 参数的补全建议来自all、所有主机别名以及各主机的labelvalue组合SelectCommand.php安装方式参见 installation。此外Selector的单测 SelectorTest.php 覆盖了典型组合all全量匹配、stageprod单条件、stageprod tierfrontendAND 匹配、prod.domain.com/front, stagebeta别名条件 OR、all tier ! frontend取反排除以及标签值为数组如stage [prod, beta]时的多值匹配——这些用例可直接作为你验证选择器行为的参考基准。九、小结Deployer 的 Selector 体系可以归纳为三层数据层主机通过setLabels()/addLabels()或 MAML 中的labels:键携带任意键值标签匹配时还会注入alias与恒真的true两个隐式标签匹配层Selector::parse()将表达式拆为,OR→AND→|值内 OR三层结构Selector::apply()按组内全真、组间任一规则求值支持与!应用层CLI 参数经 SelectCommand.php 拼接后统一求值任务内可用select()/on()动态筛选任务定义可用-select()固化范围once/oncePerNode与并行调度则复用同一套apply()判定。掌握这套机制后无论是只部署生产环境 Web 节点排除某个机房的主机还是每节点只跑一次数据库迁移都能用一行选择器精准表达让 Deployer 的批量部署始终落在你真正想要的主机集合上。【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址: https://gitcode.com/gh_mirrors/de/deployer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表