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 在 操作系统
65 每月下载量
110KB
2.5K SLoC
supervisor-rs
supervisor-rs
以前是运行应用的管家。 supervisor-rs
可以启动/重启/停止处理。
特性:
- 启动时根据特定的 yaml 文件启动不同的处理
- 在负载路径中有新配置时启动处理
- 使用特定的服务器配置启动
- 重启处理
- 停止处理
设计:
- 服务器/客户端模式
- 服务器启动 -> 从负载路径加载配置文件(如果不是静默模式) -> 执行任务
- 开始/停止/重启/尝试重启特殊处理(客户端)
配置 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 未提供时使用。值可以是 true 或 false 。当此字段为 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
。
服务器应用程序启动后,如果mode
是full
,则服务器配置加载路径下的所有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.2
和192.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
。
启动时启用特性
如果服务器的配置mode
是half
,则服务器启动时会尝试启动startup
列表中的所有子进程。
示例
#server side config
loadpaths:
- /tmp/client/
- /tmp/second/path
mode: "half"
startup:
- child1
- child2
- child3
服务器启动时会尝试启动child1
、child2
和child3。
问题解答
问:如果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
不会创建一个计时器。
只有start
、restart
和trystart
会根据repeat
字段的存在为supervisor-rs
创建一个计时器。
如果action
为空,supervisor-rs
将默认值为restart
。然而,seconds
必须有值,并且它不能为0。
如何停止重复
如我之前所说,timer
在子进程运行后立即创建。因此,您不能停止“下一个”动作,但如果您更改子进程的配置,例如删除重复字段,则“下一个”动作不会创建计时器。
这是因为所有start
、restart
和trystart
都会在执行其工作之前重新加载子进程的配置。
因此,如果子进程已经停止,或者手动在计时器完成等待并发送命令给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
登录该服务器。
然后
- 告诉您计算机中的 ssh 使用
192.168.3.3
使用密钥~/.ssh/key
(通过修改~/.ssh/config
)。这样,您就可以不指定要使用的密钥即可 ssh 登录,例如ssh user@192.168.3.3
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