44从零开始用Rust编写nginx,命令行参数的设计与解析及说明 ...

打印 上一主题 下一主题

主题 934|帖子 934|积分 2806

wmproxy

wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,七层负载均衡,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子
项目地址

国内: https://gitee.com/tickbh/wmproxy
github: https://github.com/tickbh/wmproxy
设计目标

设置启动命令行参数方便在没有配置的情况下启动。
设计事项

当你在Linux终端上输入git --help时,你会看到这样的打印:
  1. shell> git --help
  2. usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
  3.            [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
  4.            [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
  5.            [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
  6.            <command> [<args>]
  7. These are common Git commands used in various situations:
  8. start a working area (see also: git help tutorial)
  9.    clone      Clone a repository into a new directory
  10.    init       Create an empty Git repository or reinitialize an existing one
  11. ...... <omitted>
复制代码
Git程序支持一长串参数。我们以它为例来讨论程序的参数应该是什么样的。
为了给用户给予一个良好的命令行界面,程序的参数处理部分应该支持以下功能:

  • 接受参数的选项
  • 不带任何参数的标志/开关
  • 长名称(以双连字符开头,如--paginate)和短名称(以单连字符开头,如-p)
  • 友好的帮助信息--help
  • 子命令(如git add)
通过命令行我们可以执行程序中的非常多的功能,也就是命令行让程序可以在无需GUI的情况下拥有无限丰富的功能。
RUST中的命令行解析

在这里以bpaf来举例,也是本项目中选择的命令行解析库,相对来说他支持宏的同时也支持比较丰富的程序中的组合,也拥有较多的demo可以参考如何使用:
  1. use bpaf::{short, Bpaf, Parser};
  2. use std::path::PathBuf;
  3. #[derive(Debug, Clone, Bpaf)]
  4. #[bpaf(options, version)]
  5. #[allow(dead_code)]
  6. struct Opts {
  7.     /// 是否开始调试模式
  8.     #[bpaf(short, long)]
  9.     debug: bool,
  10.     /// 这是一个注释,将被忽略
  11.     #[bpaf(external(verbose))]
  12.     verbose: usize,
  13.     /// 设置速度, 拥有默认速度
  14.     #[bpaf(argument("SPEED"), fallback(42.0), display_fallback)]
  15.     speed: f64,
  16.     /// 输出目录
  17.     output: PathBuf,
  18.     /// 将检测必须为正数
  19.     #[bpaf(guard(positive, "must be positive"), fallback(1))]
  20.     nb_cars: u32,
  21.     files_to_process: Vec<PathBuf>,
  22. }
  23. fn verbose() -> impl Parser<usize> {
  24.     // number of occurrences of the v/verbose flag capped at 3
  25.     short('v')
  26.         .long("verbose")
  27.         .help("启动verbose模式\n根据输入的v的个数来判定等级\n可以 -v -v -v 或者 -vvv")
  28.         .req_flag(())
  29.         .many()
  30.         .map(|xs| xs.len())
  31.         .guard(|&x| x <= 3, "最多仅能输入三个v")
  32. }
  33. fn positive(input: &u32) -> bool {
  34.     *input > 1
  35. }
  36. fn main() {
  37.     println!("{:#?}", opts().run());
  38. }
复制代码
通过启动打印--help信息可知cargo run --example arg -- --help
  1. PS D:\my\wmproxy> cargo run --example arg -- --help
  2.    Compiling wmproxy v0.2.5 (D:\my\wmproxy)
  3.     Finished dev [unoptimized + debuginfo] target(s) in 1.12s
  4.      Running `target\debug\examples\arg.exe --help`
  5. Usage: arg.exe [-d] [-v]... [--speed=SPEED] --output=ARG [--nb-cars=ARG] [--files-to-process=ARG]...
  6. Available options:
  7.     -d, --debug        是否开始调试模式
  8.     -v, --verbose      启动verbose模式 根据输入的v的个数来判定等级 可以 -v -v -v 或者 -vvv        
  9.         --speed=SPEED  设置速度, 拥有默认速度
  10.                        [default: 42]
  11.         --output=ARG   输出目录
  12.         --nb-cars=ARG  将检测必须为正数
  13.         --files-to-process=ARG
  14.     -h, --help         Prints help information
  15.     -V, --version      Prints version information
复制代码
我们可以通过简单的配置来拥有较完整的命令行的模式的支持,包括默认参数fallback,及完整的help信息。
rust中还有其它较为知名的解析库,图片来源于网上,可根据项目的需要进行相应的选择。

命令行参数

该项目选择用的是子命令的模式


  • wmproxy run        启动命令
  • wmproxy start  启动命令, 但在后台运行
  • wmproxy stop  关闭命令
  • wmproxy reload  进行重载配置
  • wmproxy check  检查配置是否正确
  • wmproxy proxy      代理及内网穿透相关功能
  • wmproxy file-server  启动文件服务器
  • wmproxy reverse-proxy  启动负载均衡服务器
  • wmproxy ws-proxy  Websocket协议转发相关
  • wmproxy version  打印当前版本号
wmproxy run

通过命令wmproxy run --help可以得到
  1. Usage: wmproxy.exe run -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control]
  2. [-v] [--default-level=ARG]
  3. Available options:
  4.     -c, --config=ARG         配置文件路径
  5.         --pidfile=ARG        写入进程id文件
  6.         --control=ARG        输入控制台的监听地址
  7.                              [default: 127.0.0.1:8837]
  8.         --disable-stdout     禁用默认输出
  9.         --disable-control    禁用控制微端
  10.     -v, --verbose            是否显示更多日志
  11.         --default-level=ARG  设置默认等级
  12.     -h, --help               Prints help information
复制代码
通过配置文件启动程序如:
  1. wmproxy run -c config/reverse.toml
复制代码
wmproxy start

通过命令wmproxy start --help可以得到
  1. Usage: wmproxy.exe start -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control]
  2. [-v] [--default-level=ARG]
  3. Available options:
  4.     -c, --config=ARG         配置文件路径
  5.         --pidfile=ARG        写入进程id文件
  6.         --control=ARG        输入控制台的监听地址
  7.                              [default: 127.0.0.1:8837]
  8.         --disable-stdout     禁用默认输出
  9.         --disable-control    禁用控制微端
  10.     -v, --verbose            是否显示更多日志
  11.         --default-level=ARG  设置默认等级
  12.     -h, --help               Prints help information
复制代码
通过配置文件启动程序,我们通过观察可以得知参数与run一模一样,差别是该参数将后台启动。
示例如:
  1. wmproxy start -c config/reverse.toml
复制代码
wmproxy stop

通过命令wmproxy stop --help可以得到
  1. Usage: wmproxy.exe stop [-c=ARG] [-p=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control
  2. ] [-v] [--default-level=ARG]
  3. Available options:
  4.     -c, --config=ARG         配置文件路径
  5.     -p, --pidfile=ARG        写入进程id文件
  6.     -u, --url=ARG            控制微端地址
  7.         --control=ARG        输入控制台的监听地址
  8.                              [default: 127.0.0.1:8837]
  9.         --disable-stdout     禁用默认输出
  10.         --disable-control    禁用控制微端
  11.     -v, --verbose            是否显示更多日志
  12.         --default-level=ARG  设置默认等级
  13.     -h, --help               Prints help information
复制代码
此处我们通过三种方式将其关闭,一种是配置文件,一种是pid文件,一种是控制微端的url。
示例如:
  1. wmproxy stop -c config/reverse.toml
  2. 或者
  3. wmproxy stop -p wmproxy.pid
  4. 或者
  5. wmproxy stop -u http://127.0.0.1:8837
复制代码
wmproxy reload

通过命令wmproxy reload --help可以得到
  1. Usage: wmproxy.exe reload [-c=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control] [-v
  2. ] [--default-level=ARG]
  3. Available options:
  4.     -c, --config=ARG         配置文件路径
  5.     -u, --url=ARG            控制微端地址
  6.         --control=ARG        输入控制台的监听地址
  7.                              [default: 127.0.0.1:8837]
  8.         --disable-stdout     禁用默认输出
  9.         --disable-control    禁用控制微端
复制代码
此处我们通过三种方式将其重载,一种是配置文件,一种是控制微端的url。
示例如:
  1. wmproxy reload -c config/reverse.toml
  2. 或者
  3. wmproxy reload -u http://127.0.0.1:8837
复制代码
wmproxy proxy

代理类相对参数比较复杂
通过命令wmproxy proxy --help可以得到
  1. Usage: wmproxy.exe proxy [-b=ARG] [--flag=ARG] [--mode=ARG] [-S=ARG] [--user=ARG] [--pass=ARG] [--udp-bind
  2. =ARG] [--map-http-bind=ARG] [--map-https-bind=ARG] [--map-tcp-bind=ARG] [--map-proxy-bind=ARG] [--map-cert
  3. =ARG] [--map-key=ARG] [--center] [--ts] [--tc] [--two-way-tls] [--domain=ARG] [--cert=ARG] [--key=ARG
  4. ] [--mappings=ARG]... [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG
  5. ]
  6. 代理类, 一个代理类启动一种类型的代理
  7.     -b, --bind-addr=ARG       代理绑定端口地址
  8.                               [default: 127.0.0.1:8090]
  9.         --flag=ARG            代理种类, 如http https socks5
  10.         --mode=ARG            启动程序类型
  11.     -S, --server=ARG          连接代理服务端地址
  12.         --user=ARG            用于socks验证及中心服务器验证
  13.         --pass=ARG            用于socks验证及中心服务器验证
  14.         --udp-bind=ARG        udp的绑定地址
  15.         --map-http-bind=ARG   内网http的映射地址
  16.         --map-https-bind=ARG  内网https的映射地址
  17.         --map-tcp-bind=ARG    内网tcp的映射地址
  18.         --map-proxy-bind=ARG  内网代理的映射地址
  19.         --map-cert=ARG        内网映射的证书cert
  20.         --map-key=ARG         内网映射的证书key
  21.         --center              是否启用协议转发
  22.         --ts                  连接服务端是否启用tls
  23.         --tc                  接收客户端是否启用tls
  24.         --two-way-tls         双向认证是否启用
  25.         --domain=ARG          tls证书所用的域名
  26.         --cert=ARG            公开的证书公钥文件
  27.         --key=ARG             隐私的证书私钥文件
  28.         --mappings=ARG
  29. Available options:
  30.         --control=ARG         输入控制台的监听地址
  31.                               [default: 127.0.0.1:8837]
  32.         --disable-stdout      禁用默认输出
  33.         --disable-control     禁用控制微端
  34.     -v, --verbose             是否显示更多日志
  35.         --default-level=ARG   设置默认等级
  36.     -h, --help                Prints help information
复制代码
如果仅仅启动代理功能可以
  1. wmproxy proxy -b="127.0.0.1:8090"
  2. 或者
  3. wmproxy proxy -b "127.0.0.1:8090"
复制代码
即可启动8090开始的http/https/socks5代理
wmproxy file-server

启动文件服务
通过命令wmproxy file-server --help可以得到
  1. Usage: wmproxy.exe file-server [-r=ARG] [-l=ARG] [-d=ARG] [-b] [--access-log=ARG] [--control=ARG] [--disable-stdout
  2. ] [--disable-control] [-v] [--default-level=ARG]
  3. Available options:
  4.     -r, --root=ARG           静态文件根目录路径
  5.     -l, --listen=ARG         监听地址
  6.                              [default: 127.0.0.1:80]
  7.     -d, --domain=ARG         域名地址
  8.     -b, --browse             是否支持目录
  9.         --access-log=ARG     访问日志放的位置如"logs/access.log trace"
  10.         --control=ARG        输入控制台的监听地址
  11.                              [default: 127.0.0.1:8837]
  12.         --disable-stdout     禁用默认输出
  13.         --disable-control    禁用控制微端
  14.     -v, --verbose            是否显示更多日志
  15.         --default-level=ARG  设置默认等级
  16.     -h, --help               Prints help information
复制代码
如果仅仅启动代理功能可以
  1. wmproxy file-server
  2. 或者
  3. wmproxy file-server -l :8080 -r "d:/my/wmproxy"
复制代码
即可启动文件服务器对其服务。
wmproxy reverse-proxy

启动负载均衡服务
通过命令wmproxy reverse-proxy --help可以得到
  1. Usage: wmproxy.exe reverse-proxy [-f=ARG] -t=ARG [-H=ARG]... [--access-log=ARG] [--tls] [--control=ARG
  2. ] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG]
  3. Available options:
  4.     -f, --from=ARG           负载均衡来源地址
  5.                              [default: 127.0.0.1:80]
  6.     -t, --to=ARG             负载均衡映射地址
  7.     -H, --header=ARG         头部信息修改如 "proxy x-forward-for {client_ip}"
  8.         --access-log=ARG     访问日志放的位置如"logs/access.log trace"
  9.         --tls                是否映射到https上
  10.         --control=ARG        输入控制台的监听地址
  11.                              [default: 127.0.0.1:8837]
  12.         --disable-stdout     禁用默认输出
  13.         --disable-control    禁用控制微端
  14.     -v, --verbose            是否显示更多日志
  15.         --default-level=ARG  设置默认等级
  16.     -h, --help               Prints help information
复制代码
需要配置从源目标到目标的信息,可以配置header等相应的信息。
  1. wmproxy reverse-proxy
  2. 或者
  3. wmproxy reverse-proxy -t :8080
复制代码
即可启动负载均衡服务对其服务。
wmproxy ws-proxy

启动websocket协议转发服务
通过命令wmproxy ws-proxy --help可以得到
  1. Usage: wmproxy.exe ws-proxy [-f=ARG] -t=ARG [--access-log=ARG] --mode=<ws2tcp,tcp2ws,tcp2wss> [--ws]
  2. [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG]
  3. Available options:
  4.     -f, --from=ARG           负载均衡来源地址
  5.                              [default: 127.0.0.1:80]
  6.     -t, --to=ARG             负载均衡映射地址
  7.         --access-log=ARG     访问日志放的位置如"logs/access.log trace"
  8.         --mode=<ws2tcp,tcp2ws,tcp2wss>  当前代理的模式
  9.         --domain=ARG         当前域名
  10.         --ws                 是否支持websocket
  11.         --control=ARG        输入控制台的监听地址
  12.                              [default: 127.0.0.1:8837]
复制代码
模式中

  • ws2tcp 指websocket的流量转成tcp
  • tcp2ws 指tcp的流量转成websocket
  • tcp2wss 指tcp的流量转成websocket tls流量
  1. # 将流量通过ws转成tcp
  2. wmproxy ws-proxy -t :8082 --mode ws2tcp
  3. 或者
  4. # 将流量通过tcp转成ws
  5. wmproxy ws-proxy -t :8099 --mode tcp2ws
复制代码
即可启动websocket的流量。
wmproxy version

打印当前软件的版本号
小结

好的命令行可以执行更强大的功能,也能让人更好的理解你的程序,这需要有一个好的帮助系统,也需要有一个强大的解析能力。此章讲述了命令行的执行功能,希望可以帮助到你的使用。
点击 [关注][在看][点赞] 是对作者最大的支持

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表