#yaml-config #server #public-key #server-side #start #encryption-key #child

bin+lib supervisor-rs

通过服务器管理(启动/停止/重启等)进程

17 个版本

0.8.5 2024 年 1 月 5 日
0.8.4 2023 年 4 月 20 日
0.8.3 2021 年 10 月 22 日
0.8.2 2021 年 6 月 14 日
0.5.9 2019 年 7 月 16 日

#73操作系统

Download history 1/week @ 2024-03-08 9/week @ 2024-03-29 1/week @ 2024-04-05

65 每月下载量

MIT 许可证

110KB
2.5K SLoC

supervisor-rs

supervisor-rs 以前是运行应用的管家。 supervisor-rs 可以启动/重启/停止处理。

特性:

  • 启动时根据特定的 yaml 文件启动不同的处理
  • 在负载路径中有新配置时启动处理
  • 使用特定的服务器配置启动
  • 重启处理
  • 停止处理

设计:

  1. 服务器/客户端模式
  2. 服务器启动 -> 从负载路径加载配置文件(如果不是静默模式) -> 执行任务
  3. 开始/停止/重启/尝试重启特殊处理(客户端)

配置 yaml 文件格式:

server.yaml 的示例

# server side config
loadpaths:
  - /tmp/client/
  - /tmp/second/path
  
mode: "half"
startup:
  - child1
  - child2
  
encrypt: on
pub_keys_path:
  - vault1
  - vault2

#ipv6: true
listener_addr: 127.0.0.1
字段 用法
loadpaths 所有子配置文件路径的列表。
mode 启动模式。值可以是 "quiet"、"half" 或 "full"
startup mode 是 "half" 时,此列表中的子项将启动
encrypt 加密模式。值可以是 "on" 或 "off"
pub_keys_path 当加密是 "on" 时,此字段包括公钥路径列表
listener_addr 服务器端监听的地址
ipv6 仅当 listener_addr 未提供时使用。值可以是 truefalse。当此字段为 true 时,supervisor-rs 服务器端将监听 "::" 而不是 "0.0.0.0"

子配置的 yaml 示例

#each child config in loadpath of server config
command: /tmp/test
output:
  - stdout: aaaaaa
    mode: create

  - stderr: nnnnn
    mode: append

repeat:
  action: restart
  seconds: 5

hooks:
  - prehook: start child
  - posthook: start child

用法

您可以直接下载编译后的二进制文件。

您可以从cargo.io安装,运行 cargo install supervisor-rs

服务器端

在shell中运行 supervisor-rs-server /tmp/server.yml,您可以将服务器配置yaml文件更改到任何您想要的位置。如果没有指定配置路径,supervisor将在/tmp中查找server.yml

服务器应用程序启动后,如果modefull,则服务器配置加载路径下的所有application yaml文件都将由应用程序运行。这意味着那里的每个yaml文件都应该是合法的应用程序配置文件,否则服务器无法启动。

服务器端默认模式是quiet,意味着服务器将记录loadphths,但不会自动启动子进程。

每个子进程都以yaml文件的filename命名。如果有多个加载路径,请确保没有yaml文件具有相同的名称

在运行时更改服务器配置

服务器启动后,配置路径是严格的,但配置内容是可协商的。这意味着您可以更改配置的内容,但不能更改其位置。

例如,您只想向服务器添加一个新的loadpaths。您可以轻松更改服务器配置中的loadpaths。但是,服务器不会立即更改,因为没有必要。

然后,您将一个子配置放在您刚刚添加的loadpath中,然后启动它(转到客户端使用说明)。服务器将重新读取配置并启动它。所有子进程都在配置所在的同一路径(子进程处理的当前路径)中运行。

技术上,服务器只保留配置路径,并在需要操作子进程或查找关键文件时再次读取它。

命令演示

使用特殊配置文件运行服务器:supervisor-rs-server ./test/server.yml

客户端

操作子进程:

supervisor-rs-client restart child0 on localhost将在本地主机上重启进程child0

supervisor-rs-client restart child0 on 198.0.0.2将在192.0.0.2上重启进程child0,我假设您正在此主机上运行服务器端应用程序;

supervisor-rs-client restart child0 on "198.0.0.2, 198.0.0.3"将在192.0.0.2192.0.0.3上重启进程child0,我假设您在这些主机上运行服务器端应用程序;

版本0.6以上的命令与supervisor-rs-client restart child0 on 198.0.0.2 on 198.0.0.3等效。

对于 check / kill / info 命令,无需提供子进程名称。

命令

命令 行为
重启 在服务器上重启子进程。该子进程必须正在运行(服务器应用程序)。否则,请使用 start 命令。
启动 启动新的子进程。此命令可以启动一次性命令,或新配置放入加载路径。并且,start 命令不会关心子进程本身发生的事情。如果它立即启动并崩溃,supervisor 仍会返回成功消息。使用 check 命令来检查它是否正在运行。
停止 停止正在运行的子进程。必须提供子进程名称。如果想要停止所有子进程,请使用 stop all
检查 返回所有正在 运行 的子进程的摘要。如果子进程未运行,无论原因如何,它们都将从幼儿园的表中删除。
尝试启动 用于 CI/CD 的特殊命令以启动子进程。 restart 仅在子进程正在运行时才有效;start 仅在子进程未运行时才有效。 trystart 无论如何都会运行子进程处理,如果正在运行,则重启;如果没有运行,则启动它。
杀死 杀死将终止服务器并返回服务器的最后信息。
信息 获取服务器自身的通用信息。

使用密钥对验证客户端

当服务器端处于 encrypt 模式时,服务器端将检查接收到的数据是否可以通过 pub_keys_path 中的公钥解密。

示例

服务器端配置:

loadpaths:
  - /tmp/client/
  - /tmp/second/path
  
encrypt: "on"
pub_keys_path:
  - /tmp/pub_keys/
  - /tmp/pub_keys2/

当服务器以 encrypt: "on"(仅支持小写)启动时,服务器端将从客户端接收的命令中提取密钥名称,并在 pub_keys_path 中找到具有相同 filename 的公钥(仅支持 .pem 文件)。与子进程名称一样,密钥的名称也等于密钥文件的名称。因此,请确保没有密钥文件具有相同的名称。

客户端命令

在客户端,只需运行 supervisor-rs-client restart child0 on 198.0.0.2 on 198.0.0.3 with /path/to/key/keyname1.pem

然后 supervisor 将寻找命名为 keyname1 的密钥文件。与您可以在 supervisor 启动后更改子进程配置一样灵活,您也可以在 supervisor 运行时将公钥文件放入 pub_keys_path

注意:您只能在每个命令中有一个 with /bla/bla/key.pem

生成密钥对

步骤 1:生成私钥 openssl genrsa -out private.pem 4096

记住:密钥大小应该小于或等于 4096

步骤 2:生成公钥 openssl rsa -in private.pem -outform PEM -pubout -out public.pem

然后,将公钥放入服务器的一个pub_keys_path路径中。您发送到服务器的每个命令都应该有with /path/to/private.pem

注意

当supervisor-rs运行时,您不能更改加密模式。但您可以修改pub_keys_path

启动时启用特性

如果服务器的配置modehalf,则服务器启动时会尝试启动startup列表中的所有子进程。

示例

#server side config
loadpaths:
  - /tmp/client/
  - /tmp/second/path
  
mode: "half"
startup:
  - child1
  - child2
  - child3

服务器启动时会尝试启动child1child2child3

问题解答

问:如果child3不存在怎么办?

答:服务器将在startup中查找子进程,如果某些子进程在loadpaths中不存在,服务器将跳过它们。

问:如果我忘记将模式设置为half怎么办?

答:服务器的默认模式是静默模式,启动列表仅在half模式下使用,否则,startup不会产生任何效果。

重复特性

如果子进程的配置有repeat字段

#file name (child name) is demo.yml
command: /tmp/test
output:
  - stdout: aaaaaa
    mode: create

  - stderr: nnnnn
    mode: append
repeat:
  action: restart
  seconds: 5 #only support seconds now
  

那么,当您启动它时,supervisor-rs将设置一个计时器并等待时间到达后发送命令。例如,上面的配置将每5秒运行一次restart demo

action的值是我们用于supervisor-rs-client的命令,因此您甚至可以使用具有repeat字段的stop子进程。但是,因此,supervisor-rs不会创建一个计时器。

只有startrestarttrystart会根据repeat字段的存在为supervisor-rs创建一个计时器。

如果action为空,supervisor-rs将默认值为restart。然而,seconds必须有值,并且它不能为0。

如何停止重复

如我之前所说,timer在子进程运行后立即创建。因此,您不能停止“下一个”动作,但如果您更改子进程的配置,例如删除重复字段,则“下一个”动作不会创建计时器。

这是因为所有startrestarttrystart都会在执行其工作之前重新加载子进程的配置。

因此,如果子进程已经停止,或者手动在计时器完成等待并发送命令给supervisor之前重新启动,计时器不会过时?计时器将检查子进程是否具有与创建计时器时相同的处理ID。如果此检查通过,计时器将正常执行其工作,否则,由于子进程当前不是之前的孩子,计时器将不会执行任何操作。

钩子特性

每个子进程可以有两个钩子,一个prehook,一个posthook。在主子进程start/restart之前运行prehook命令。在子进程stop之后运行posthook

如果具有另一个prehook的子进程,这意味着存在一个预钩子链,它们将依次运行,并且不能有钩子循环。

示例

command: sleep 10
hooks:
  - prehook: start child
  - posthook: start child

自定义监听地址和 IPV6 支持

如果您想使用特定的监听IP地址而不是默认的监听地址(0.0.0.0),您可以在您的服务器端配置yaml文件中轻松地添加listener_addr字段。

示例

#server side config
loadpaths:
  - /tmp/client/
  - /tmp/second/path

listener_addr: "127.0.0.1" # only listen local

如果您想使用 IPV6 而不是 IPV4,只需将 listener_addr 更改为您想要的 IPV6 地址。或者,只需将 ipv6 字段设置为 true

示例

#server side config
loadpaths:
  - /tmp/client/
  - /tmp/second/path

listener_addr: "::1" # only listen local ipv6

ipv6 字段仅在未提供 任何 listener_addr 时使用,或者 supervisor-rs 服务器端会忽略 ipv6。如果没有提供 listener_addr,并且 ipv6 为真,则 supervisor-rs 将以监听 ipv6 地址 :: 启动。

SSH-agent 代理隧道特性

默认情况下,supervisor-rs-server 监听 0.0.0.0,这意味着所有可以到达 supervisor-rs-server 主机的服务器都可以向 supervisor-rs-server 发送命令。然后我们有了 密钥对 功能来加密/授权客户端的身份。

如果我们处于内网中,监听 0.0.0.0 或特定的 IP 地址并不重要。防火墙和路由表会为我们完成工作。此外,密钥对 可以确保只有某些人可以向 supervisor-rs-server 发送。

然而,如果我们部署在某个云服务中,我们的服务器就会向奇怪的世界开放。我们可能不相信外部,仍然想通过 ssh 登录主机服务器并完成我们的工作。这就是这个功能出现的原因。

如何操作

服务器端

无需任何额外配置即可启用此功能。对我来说,我只是将 listener_addr 设置为 127.0.0.1,以确保所有外部计算机都无法与 supervisor-rs-server 通信。

此外,确保您的服务器上 supervisor-rs-client 在 PATH 中。如果您通过 cargo install supervisor-rs 安装了 supervisor-rs,我猜您已经有了它。

客户端

假设我们的 supervisor-rs-server 部署在 192.168.3.3 上。我们可以使用 ssh -i ~/.ssh/key user@192.168.3.3 登录该服务器。

然后

  1. 告诉您计算机中的 ssh 使用 192.168.3.3 使用密钥 ~/.ssh/key(通过修改 ~/.ssh/config)。这样,您就可以不指定要使用的密钥即可 ssh 登录,例如 ssh user@192.168.3.3
  2. ssh-add ~/.ssh/key 用于在 ssh-agent 中添加密钥。

在这些之后,您可以在 ssh 上运行 supervisor-rs-client check。所有用法相同,您只需要更改主机(IP 地址)字段为 ssh://{username}@{hostip}

如果发生意外怎么办

  • 如果 supervisor-rs 被 kill 杀死,子进程不会停止,它们将由系统接管。
  • 如果 supervisor-rs 发生恐慌,子进程不会停止。

如果 supervisor-rs-server 有问题,请转到日志以获取更多信息

交叉编译

brewtap filosottile/musl-cross && brew安装 FiloSottile/musl-cross/musl-cross

安装 musl-cross 之后,which x86_64-linux-musl-gcc 将给出一个结果,例如 /usr/local/bin/x86_64-linux-musl-gcc

~/.cargo/config 中提供配置

[target.x86_64-unknown-linux-musl]
linker = "x86_64-linux-musl-gcc"

然后,env CC_x86_64_unknown_linux_musl=x86_64-linux-musl-gcc cargo build --target=x86_64-unknown-linux-musl --release,在我的本地机器上没有错误。

依赖关系

~6–11MB
~230K SLoC