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

wmproxy

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

项目地址

国内: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

设计目标

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

设计事项

当你在Linux终端上输入git --help时,你会看到这样的打印:

shell> git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]
 
These are common Git commands used in various situations:
 
start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one
...... <omitted>

Git程序支持一长串参数。我们以它为例来讨论程序的参数应该是什么样的。

为了给用户给予一个良好的命令行界面,程序的参数处理部分应该支持以下功能:

  • 接受参数的选项

  • 不带任何参数的标志/开关

  • 长名称(以双连字符开头,如--paginate)和短名称(以单连字符开头,如-p)

  • 友好的帮助信息--help

  • 子命令(如git add)

通过命令行我们可以执行程序中的非常多的功能,也就是命令行让程序可以在无需GUI的情况下拥有无限丰富的功能。

RUST中的命令行解析

在这里以bpaf来举例,也是本项目中选择的命令行解析库,相对来说他支持宏的同时也支持比较丰富的程序中的组合,也拥有较多的demo可以参考如何使用:

use bpaf::{short, Bpaf, Parser};
use std::path::PathBuf;
 
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options, version)]
#[allow(dead_code)]
struct Opts {
    /// 是否开始调试模式
    #[bpaf(short, long)]
    debug: bool,
    /// 这是一个注释,将被忽略
    #[bpaf(external(verbose))]
    verbose: usize,
    /// 设置速度, 拥有默认速度
    #[bpaf(argument("SPEED"), fallback(42.0), display_fallback)]
    speed: f64,
    /// 输出目录
    output: PathBuf,
 
    /// 将检测必须为正数
    #[bpaf(guard(positive, "must be positive"), fallback(1))]
    nb_cars: u32,
    files_to_process: Vec<PathBuf>,
}
 
fn verbose() -> impl Parser<usize> {
    // number of occurrences of the v/verbose flag capped at 3
    short('v')
        .long("verbose")
        .help("启动verbose模式\n根据输入的v的个数来判定等级\n可以 -v -v -v 或者 -vvv")
        .req_flag(())
        .many()
        .map(|xs| xs.len())
        .guard(|&x| x <= 3, "最多仅能输入三个v")
}
 
fn positive(input: &u32) -> bool {
    *input > 1
}
 
fn main() {
    println!("{:#?}", opts().run());
}

通过启动打印--help信息可知cargo run --example arg -- --help

PS D:\my\wmproxy> cargo run --example arg -- --help
   Compiling wmproxy v0.2.5 (D:\my\wmproxy)
    Finished dev [unoptimized + debuginfo] target(s) in 1.12s
     Running `target\debug\examples\arg.exe --help`
Usage: arg.exe [-d] [-v]... [--speed=SPEED] --output=ARG [--nb-cars=ARG] [--files-to-process=ARG]...
 
Available options:
    -d, --debug        是否开始调试模式
    -v, --verbose      启动verbose模式 根据输入的v的个数来判定等级 可以 -v -v -v 或者 -vvv        
        --speed=SPEED  设置速度, 拥有默认速度
                       [default: 42]
        --output=ARG   输出目录
        --nb-cars=ARG  将检测必须为正数
        --files-to-process=ARG
    -h, --help         Prints help information
    -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

通过命令wmproxy run --help可以得到

Usage: wmproxy.exe run -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control]
[-v] [--default-level=ARG]
 
Available options:
    -c, --config=ARG         配置文件路径
        --pidfile=ARG        写入进程id文件
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端
    -v, --verbose            是否显示更多日志
        --default-level=ARG  设置默认等级
    -h, --help               Prints help information

通过配置文件启动程序如:

wmproxy run -c config/reverse.toml

wmproxy start

通过命令wmproxy start --help可以得到

Usage: wmproxy.exe start -c=ARG [--pidfile=ARG] [--control=ARG] [--disable-stdout] [--disable-control]
[-v] [--default-level=ARG]
 
Available options:
    -c, --config=ARG         配置文件路径
        --pidfile=ARG        写入进程id文件
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端
    -v, --verbose            是否显示更多日志
        --default-level=ARG  设置默认等级
    -h, --help               Prints help information

通过配置文件启动程序,我们通过观察可以得知参数与run一模一样,差别是该参数将后台启动。示例如:

wmproxy start -c config/reverse.toml
wmproxy stop

通过命令wmproxy stop --help可以得到

Usage: wmproxy.exe stop [-c=ARG] [-p=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control
] [-v] [--default-level=ARG]
 
Available options:
    -c, --config=ARG         配置文件路径
    -p, --pidfile=ARG        写入进程id文件
    -u, --url=ARG            控制微端地址
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端
    -v, --verbose            是否显示更多日志
        --default-level=ARG  设置默认等级
    -h, --help               Prints help information

此处我们通过三种方式将其关闭,一种是配置文件,一种是pid文件,一种是控制微端的url。示例如:

wmproxy stop -c config/reverse.toml
或者
wmproxy stop -p wmproxy.pid
或者
wmproxy stop -u http://127.0.0.1:8837
wmproxy reload

通过命令wmproxy reload --help可以得到

Usage: wmproxy.exe reload [-c=ARG] [-u=ARG] [--control=ARG] [--disable-stdout] [--disable-control] [-v
] [--default-level=ARG]
 
Available options:
    -c, --config=ARG         配置文件路径
    -u, --url=ARG            控制微端地址
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端

此处我们通过三种方式将其重载,一种是配置文件,一种是控制微端的url。

示例如:

wmproxy reload -c config/reverse.toml
或者
wmproxy reload -u http://127.0.0.1:8837
wmproxy proxy

代理类相对参数比较复杂通过命令wmproxy proxy --help可以得到

Usage: wmproxy.exe proxy [-b=ARG] [--flag=ARG] [--mode=ARG] [-S=ARG] [--user=ARG] [--pass=ARG] [--udp-bind
=ARG] [--map-http-bind=ARG] [--map-https-bind=ARG] [--map-tcp-bind=ARG] [--map-proxy-bind=ARG] [--map-cert
=ARG] [--map-key=ARG] [--center] [--ts] [--tc] [--two-way-tls] [--domain=ARG] [--cert=ARG] [--key=ARG
] [--mappings=ARG]... [--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG
]
 
代理类, 一个代理类启动一种类型的代理
    -b, --bind-addr=ARG       代理绑定端口地址
                              [default: 127.0.0.1:8090]
        --flag=ARG            代理种类, 如http https socks5
        --mode=ARG            启动程序类型
    -S, --server=ARG          连接代理服务端地址
        --user=ARG            用于socks验证及中心服务器验证
        --pass=ARG            用于socks验证及中心服务器验证
        --udp-bind=ARG        udp的绑定地址
        --map-http-bind=ARG   内网http的映射地址
        --map-https-bind=ARG  内网https的映射地址
        --map-tcp-bind=ARG    内网tcp的映射地址
        --map-proxy-bind=ARG  内网代理的映射地址
        --map-cert=ARG        内网映射的证书cert
        --map-key=ARG         内网映射的证书key
        --center              是否启用协议转发
        --ts                  连接服务端是否启用tls
        --tc                  接收客户端是否启用tls
        --two-way-tls         双向认证是否启用
        --domain=ARG          tls证书所用的域名
        --cert=ARG            公开的证书公钥文件
        --key=ARG             隐私的证书私钥文件
        --mappings=ARG
 
Available options:
        --control=ARG         输入控制台的监听地址
                              [default: 127.0.0.1:8837]
        --disable-stdout      禁用默认输出
        --disable-control     禁用控制微端
    -v, --verbose             是否显示更多日志
        --default-level=ARG   设置默认等级
    -h, --help                Prints help information

如果仅仅启动代理功能可以

wmproxy proxy -b="127.0.0.1:8090"
或者
wmproxy proxy -b "127.0.0.1:8090"

即可启动8090开始的http/https/socks5代理

wmproxy file-server

启动文件服务通过命令wmproxy file-server --help可以得到

Usage: wmproxy.exe file-server [-r=ARG] [-l=ARG] [-d=ARG] [-b] [--access-log=ARG] [--control=ARG] [--disable-stdout
] [--disable-control] [-v] [--default-level=ARG]
 
Available options:
    -r, --root=ARG           静态文件根目录路径
    -l, --listen=ARG         监听地址
                             [default: 127.0.0.1:80]
    -d, --domain=ARG         域名地址
    -b, --browse             是否支持目录
        --access-log=ARG     访问日志放的位置如"logs/access.log trace"
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端
    -v, --verbose            是否显示更多日志
        --default-level=ARG  设置默认等级
    -h, --help               Prints help information

如果仅仅启动代理功能可以

wmproxy file-server
或者
wmproxy file-server -l :8080 -r "d:/my/wmproxy"

即可启动文件服务器对其服务。

wmproxy reverse-proxy

启动负载均衡服务通过命令wmproxy reverse-proxy --help可以得到

Usage: wmproxy.exe reverse-proxy [-f=ARG] -t=ARG [-H=ARG]... [--access-log=ARG] [--tls] [--control=ARG
] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG]
 
Available options:
    -f, --from=ARG           负载均衡来源地址
                             [default: 127.0.0.1:80]
    -t, --to=ARG             负载均衡映射地址
    -H, --header=ARG         头部信息修改如 "proxy x-forward-for {client_ip}"
        --access-log=ARG     访问日志放的位置如"logs/access.log trace"
        --tls                是否映射到https上
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]
        --disable-stdout     禁用默认输出
        --disable-control    禁用控制微端
    -v, --verbose            是否显示更多日志
        --default-level=ARG  设置默认等级
    -h, --help               Prints help information

需要配置从源目标到目标的信息,可以配置header等相应的信息。

wmproxy reverse-proxy
或者
wmproxy reverse-proxy -t :8080

即可启动负载均衡服务对其服务。

wmproxy ws-proxy

启动websocket协议转发服务通过命令wmproxy ws-proxy --help可以得到

Usage: wmproxy.exe ws-proxy [-f=ARG] -t=ARG [--access-log=ARG] --mode=<ws2tcp,tcp2ws,tcp2wss> [--ws]
[--control=ARG] [--disable-stdout] [--disable-control] [-v] [--default-level=ARG]
 
Available options:
    -f, --from=ARG           负载均衡来源地址
                             [default: 127.0.0.1:80]
    -t, --to=ARG             负载均衡映射地址
        --access-log=ARG     访问日志放的位置如"logs/access.log trace"
        --mode=<ws2tcp,tcp2ws,tcp2wss>  当前代理的模式
        --domain=ARG         当前域名
        --ws                 是否支持websocket
        --control=ARG        输入控制台的监听地址
                             [default: 127.0.0.1:8837]

模式中

  • ws2tcp 指websocket的流量转成tcp

  • tcp2ws 指tcp的流量转成websocket

  • tcp2wss 指tcp的流量转成websocket tls流量

# 将流量通过ws转成tcp
wmproxy ws-proxy -t :8082 --mode ws2tcp
或者
# 将流量通过tcp转成ws
wmproxy ws-proxy -t :8099 --mode tcp2ws

即可启动websocket的流量。

wmproxy version

打印当前软件的版本号

小结

好的命令行可以执行更强大的功能,也能让人更好的理解你的程序,这需要有一个好的帮助系统,也需要有一个强大的解析能力。此章讲述了命令行的执行功能,希望可以帮助到你的使用。

文章转载自:问蒙服务框架

原文链接:https://www.cnblogs.com/wmproxy/p/17983815/wmproxy44

体验地址:引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/344668.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

教育研究方法有哪些分类

教育研究方法的分类是多种多样的&#xff0c;可以从不同的角度进行划分。根据研究目的、研究范围、研究层次等&#xff0c;可以将教育研究方法分为不同的类型。 一、根据研究目的划分 基础性研究基础性研究也称为理论性研究&#xff0c;主要是为了探索和发现新的理论观点和原…

uniapp开发过程一些小坑

问题1、uniapp使用scroll-view的:scroll-into-view“lastChatData“跳到某个元素id时候&#xff0c;在app上不生效&#xff0c;小程序没问题 使用this.$nextTick或者 setTimeout(()>{that.lastChatData 元素id },500) 进行延后处理就可以了。 问题2&#xff1a;uniapp开…

运动刷步工具2.4。运动步数同步wx和支付宝

时隔一年&#xff1b;上次更新还是2022-11-26&#xff0c;陆续收到私信旧版已不能使用&#xff0c;2.4版本更新修复超时问题。后续有时间还会更新邮箱登录功能2023-11-15更新&#xff1a;修复错误超时问题测试不行的小伙伴&#xff0c;先看说明再使用&#xff01;&#xff01;&…

关于常见分布式组件高可用设计原理的理解和思考

文章目录 1. 数据存储场景和存储策略1.1 镜像模式-小规模数据1.2 分片模式-大规模数据 2. 数据一致性和高可用问题2.1 镜像模式如何保证数据一致性2.2 镜像模式如何保证数据高可用2.2.1 HA模式2.2.2 分布式选主模式 2.3 分片模式如何数据一致性和高可用 3. 大规模数据集群的架构…

垃圾收集算法

垃圾收集算法有如下几种&#xff1a; 分代收集理论&#xff1a;年龄代和老年代选择各自的垃圾收集算法。 复制算法&#xff1a;可达性分析算法找非垃圾对象&#xff0c;然后把非垃圾对象移动到另一端&#xff0c;这一端的垃圾对象清除&#xff0c;该方法浪费内…

如何查找SpringBoot应用中的请求路径(不使用idea)

背景 昨天有个同事向我咨询某个接口的物理表是哪个&#xff0c;由于公司业务较多、这块业务的确不是我负责的&#xff0c;也没有使用idea不能全局搜索(eclipse搜不到jar内的字符串)&#xff0c;也就回复了不清楚。 除了自己写代码输出servlet的路径和类外&#xff0c;发现了一…

【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍

Java技术体系方向-JVM虚拟机参数调优原理 内容简介栈上分配与逃逸分析逃逸分析(Escape Analysis)栈上分配基本思想使用场景线程私有对象 虚拟机内存逻辑图JVM内存分配源码&#xff1a;代码总体逻辑 在某些场景使用栈上分配设置JVM运行参数&#xff1a;开启逃逸模式&#xff0c;…

书生·浦语大模型--第四节课笔记--XTuner大模型单卡低成本微调

文章目录 Finetune简介指令跟随微调增量预训练微调LoRA QLoRA XTuner介绍快速上手 8GB显卡玩转LLM动手实战环节 Finetune简介 增量预训练和指令跟随 通过指令微调获得instructed LLM 指令跟随微调 一问一答的方式进行 对话模板 计算损失 增量预训练微调 不需要问题只…

数据结构:3_栈和队列

栈和队列 一.栈 1. 栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。**进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。**栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#x…

软件测试知识库+1,5款顶级自动化测试工具推荐和使用分析

“工欲善其事必先利其器”&#xff0c;在自动化测试领域&#xff0c;自动化测试工具的核心地位不容置疑的。目前市面上有很多可以支持接口测试的工具&#xff0c;在网上随便一搜就可以出来很多&#xff0c;利用自动化测试工具进行接口测试&#xff0c;可以很好的提高测试效率&a…

GPT4+Python近红外光谱数据分析及机器学习与深度学习建模

详情点击链接&#xff1a;GPT4Python近红外光谱数据分析及机器学习与深度学习建模 第一&#xff1a;GPT4 1、ChatGPT&#xff08;GPT-1、GPT-2、GPT-3、GPT-3.5、GPT-4模型的演变&#xff09; 2、ChatGPT对话初体验 3、GPT-4与GPT-3.5的区别&#xff0c;以及与国内大语言模…

最新AI系统ChatGPT网站H5系统源码,支持Midjourney绘画,GPT语音对话+ChatFile文档对话总结+DALL-E3文生图

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

Django笔记(六):DRF框架

首 前后端分离是互联网应用开发的标准使用方式&#xff0c;让前后端通过接口实现解耦&#xff0c;能够更好的进行开发和维护。 RESTful接口常见规范 在接口设计中&#xff0c;大家遵循一定的规范可以减少很多不必要的麻烦&#xff0c;例如url应有一定辨识度&#xff0c;可以…

(SSO单点登录)多个系统之间如何实现账号互通

SSO具有以下优点&#xff1a; 降低访问第三方网站风险&#xff1b;降低用户名和密码的管理成本&#xff1b;提高用户试用满意度&#xff1b;SSO使用标准的身份认证和授权协议&#xff0c;如OAuth、OpenID Connect等&#xff0c;可以保障用户身份的安全性和隐私性。 单点登录最大…

Linux 驱动开发基础知识——认识LED驱动程序 (二)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

el-select选择之后值不显示在文本框的问题解决

问题场景如下图&#xff1a; 在el-collapse-item中使用子组件&#xff0c;子组件里是el-form-item代码。el-select在for循环中&#xff0c;可以有多个。 查了一下博客&#xff0c;有的说这种场景需要给el-select添加change事件&#xff0c;加上 this.$forceUpdate() 强制刷新即…

Vue3.0里为什么要用 Proxy API 替代 defineProperty API ?

文章目录 一、Object.defineProperty二、Proxy三、总结参考文献 一、Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象 为什么能实现响应式 通过define…

Kubeadm安装单master多node节点K8S集群

kubeadm安装k8s1.25版本集群步骤 环境说明实验环境规划集群搭建规划 初始化安装k8s集群的实验环境安装虚拟机更新yum源和操作系统配置机器主机名配置主机hosts文件&#xff0c;相互之间通过主机名互相访问配置主机之间无密码登录关闭交换分区swap&#xff0c;提升性能修改机器内…

[algorithm] 自动驾驶 规划 非线性优化学习系列之1 :车辆横向运动动力学详细解释

写在前面 最近时空联合规划很火&#xff0c;想学习。由于在学校主打学习新能源电力电子方向&#xff0c;转行后也想好好零散的知识体系。计划从车辆运动动力学习&#xff0c;模型预测控制&#xff08;经典控制目前看主打应用&#xff0c;不会再去深入&#xff09;&#xff0c;…

使用js判断list中是否含有某个字符串,存在则删除,

显示上图中使用了两种方式&#xff0c; 左边的是filter将不等于userCode的元素筛选出来组成一个新的list&#xff0c; userCodeList.filter(item> item!userCode)&#xff1b;但是上面这个方法在IE浏览器中不支持&#xff0c; 所以改成了右边的方法&#xff0c;使用splice…