Skip to content

Commit 6fc0f70

Browse files
committed
change example to bin, and prepare to release v0.3
1 parent c85b9cd commit 6fc0f70

13 files changed

+140
-65
lines changed

.github/workflows/ci.yml

+4-6
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@ jobs:
5252
run: ${{ matrix.settings.build }}
5353

5454
- name: Upload artifact
55-
uses: svenstaro/upload-release-action@v2
55+
uses: actions/upload-artifact@v2
5656
with:
57-
asset_name: mproxy-${{ matrix.settings.target }}
58-
file: release/mproxy
59-
tag: ${{ github.ref }}
60-
repo_token: ${{ secrets.GITHUB_TOKEN
61-
draft: true
57+
name: mproxy-${{ matrix.settings.target }}
58+
path: release/*
59+
if-no-files-found: error

Makefile

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
.PHONY: release-mac-x86_64, release-mac-aarch64, release-linux, release-linux-aarch64
22

33
name = mproxy
4+
ctrl_name = mpublish
45
rust_path = agent
56
release-mac-x86_64:
67
mkdir -p release
78
cd $(rust_path) && cargo build --release --target=x86_64-apple-darwin
89
strip $(rust_path)/target/x86_64-apple-darwin/release/$(name)
910
otool -L $(rust_path)/target/x86_64-apple-darwin/release/$(name)
10-
cp $(rust_path)/target/x86_64-apple-darwin/release/mproxy ./release/
11+
cp $(rust_path)/target/x86_64-apple-darwin/release/$(name) ./release/
12+
strip $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name)
13+
otool -L $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name)
14+
cp $(rust_path)/target/x86_64-apple-darwin/release/$(ctrl_name) ./release/
1115

1216
# brew install wget
1317
release-mac-aarch64:
@@ -16,18 +20,27 @@ release-mac-aarch64:
1620
strip $(rust_path)/target/aarch64-apple-darwin/release/$(name)
1721
otool -L $(rust_path)/target/aarch64-apple-darwin/release/$(name)
1822
cp $(rust_path)/target/aarch64-apple-darwin/release/$(name) ./release/
23+
strip $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name)
24+
otool -L $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name)
25+
cp $(rust_path)/target/aarch64-apple-darwin/release/$(ctrl_name) ./release/
1926

2027
release-linux-aarch64:
2128
sudo apt-get install -y build-essential
2229
mkdir release
2330
cd $(rust_path) && cargo build --release --target=aarch64-unknown-linux-gnu
2431
strip $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(name)
2532
cp $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(name) ./release/
33+
cd $(rust_path) && cargo build --release --target=aarch64-unknown-linux-gnu
34+
strip $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(ctrl_name)
35+
cp $(rust_path)/target/aarch64-unknown-linux-gnu/release/$(ctrl_name) ./release/
36+
2637

2738

2839
release-linux:
2940
sudo apt-get install -y build-essential
3041
mkdir release
3142
cd $(rust_path) && cargo build --release --target=x86_64-unknown-linux-gnu
3243
strip $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name)
33-
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name) ./release
44+
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(name) ./release
45+
strip $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(ctrl_name)
46+
cp $(rust_path)/target/x86_64-unknown-linux-gnu/release/$(ctrl_name) ./release

README.md

+20-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33

44
相比于VPN,该项目代码可集成到只有 MQTT 交互的设备上,本项目的价值在于参考实现。
55

6+
## 快速开始
7+
1. 下载bin文件:[release page](./releases), `mproxy` `mpublish`
8+
2. 跑mqtt server, [这里](./tree/master/shell) 有如何快速跑测试 rmqtt 的例子,执行 `run_rmqtt.sh` 即可,生产环境参考 prod 目录下的配置。
9+
3. 编写配置文件:`mproxy.yml`,`mpublish.yml`, 可参考[agent](./tree/master/agent) 目录下的同名文件,两者要和并文件放在同一个目录下。
10+
```sh
11+
# 执行 mproxy
12+
./mproxy
13+
# or run with config
14+
./mproxy mproxy.yml
15+
16+
# 向 mproxy 分发指令
17+
./mpublish ls -ls
18+
# or run with config
19+
./mpublish --config=mpublish.conf ls -ls
20+
21+
```
22+
623
## 实现原理
724

825
在宿主上运行 `mproxy` 命令行可执行程序,通过 MQTT 连接 MQTT Server,并订阅 command 主题消息。
@@ -38,7 +55,7 @@
3855
}
3956
```
4057
### 配置文件
41-
参考 [config.yml](./agent/config.yml)
58+
参考 [mproxy.yml](./agent/mproxy.yml)[mpublish.yml](./agent/mpublish.yml)
4259

4360
### 开发
4461
Install [Rust 1.70+](https://www.rust-lang.org/),
@@ -50,11 +67,11 @@ cd shell && ./run_mqtt.sh && cd ../
5067
mprocs
5168

5269
# Check MQTT agent if is OK
53-
cd agent && cargo run --example publish_command.rs
70+
cd agent && cargo run --bin mpublish -- --config=mpublish.yml ls -ls
5471
```
5572
Web [Figma UI](https://www.figma.com/design/iyL4dms3B8AWGZS14FCRuf/RMQTT-EXEC?node-id=0%3A1&t=rnIL1LSWwQIXfZdf-1)
5673
## 限制
57-
目前只支持普通的命令, 不支持 `sudo xxx` 之类命令
74+
目前只支持普通的命令, 不支持 `sudo xxx` 需要额外输入,以及 `ls | grep xx` 使用 pipeline 的指令
5875

5976
### 应用场景举例
6077
1. 执行 `sshx`, 暴露 shell 给远端。

agent/Cargo.lock

+1-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

agent/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mproxy"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
edition = "2021"
55

66
[dependencies]
@@ -19,7 +19,7 @@ anyhow = "1"
1919
serde_yml = "0.0.7"
2020
serde = { version = "1.0.202", features = ["derive"] }
2121
serde_json = "1.0"
22-
etcetera = "0.8"
22+
#etcetera = "0.8"
2323

2424
shellish_parse = "2"
2525

agent/config.yml

-4
This file was deleted.

agent/ctrl_config.yml

-6
This file was deleted.

agent/mproxy.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
server: 'mqtt://127.0.0.1:1883' # MQTT Server
2+
client_id: test_client #MQTT Client ID
3+
#username: test #MQTT Username
4+
#password: password #MQTT Password
5+
#command_topic: cmd/$client_id #subscribe MQTT topic, listen command message, default value is cmd/$client_id
6+
#response_command_topic: cmd/$client_id/resp #the topic to publish the command result

agent/mpublish.yml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
server: 'mqtt://127.0.0.1:1883' # MQTT Server
2+
client_id: test_ctrl #MQTT Client ID
3+
#username: test_ctrl_username #MQTT Username
4+
#password: password #MQTT Password
5+
6+
subscribe_client_id: test_client #MQTT Subscribe Client ID
7+
#publish_command_topic: cmd/$client_id #the topic mpublish to pubish
8+
#response_command_topic: cmd/$client_id/resp #the topic mpublish to subscribe

agent/src/main.rs agent/src/bin/mproxy.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use tracing_subscriber::EnvFilter;
77

88
#[derive(Parser, Debug)]
99
#[clap(name = mproxy::config::APP_NAME, version = env!("CARGO_PKG_VERSION"))]
10-
#[clap(group(ArgGroup::new("cmds").required(true).args(&["CONFIG"]),))]
10+
#[clap(group(ArgGroup::new("cmds").args(&["CONFIG"]),))]
1111
struct Cli {
1212
#[clap(value_parser, name = "CONFIG")]
1313
pub config_path: Option<PathBuf>,
@@ -54,9 +54,16 @@ mod test {
5454
fn parse_cli() {
5555
let result = Cli::parse_from([APP_NAME, "config.yaml"]);
5656
println!("{:?}", result);
57-
let result = Cli::parse_from([APP_NAME, "--version"]);
57+
//let result = Cli::parse_from([APP_NAME, "--version"]);
58+
//println!("{:?}", result);
59+
//let result = Cli::parse_from([APP_NAME, "--help"]);
60+
//println!("{:?}", result);
61+
62+
let result = Cli::parse_from([APP_NAME, "--", "config.yaml"]);
5863
println!("{:?}", result);
59-
let result = Cli::parse_from([APP_NAME, "--help"]);
64+
65+
let result = Cli::parse_from([APP_NAME, "--config=config.yaml"]);
6066
println!("{:?}", result);
67+
6168
}
6269
}

agent/examples/publish_command.rs agent/src/bin/mpublish.rs

+40-10
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
use std::env;
22
use std::io::IsTerminal;
33
use std::path::PathBuf;
4+
use anyhow::bail;
5+
use clap::Parser;
46
use rumqttc::v5::{AsyncClient, MqttOptions, Incoming};
57
use rumqttc::v5::mqttbytes::QoS;
68
use tracing_subscriber::EnvFilter;
79
use mproxy::message::{RequestMessage, ResponseMessage};
10+
use mproxy::config::CTRL_APP_NAME;
11+
12+
13+
#[derive(Parser, Debug)]
14+
#[clap(name = CTRL_APP_NAME, version = env!("CARGO_PKG_VERSION"))]
15+
struct Cli {
16+
#[arg(short, long, value_name = "FILE")]
17+
pub config: Option<PathBuf>,
18+
pub command: Vec<String>,
19+
}
820

921
#[tokio::main]
1022
async fn main() -> anyhow::Result<()> {
11-
let args:Vec<String> = env::args().collect();
12-
let command = if args.len() > 1 {
13-
args.iter().skip(1).map(|x|x.to_string()).collect::<Vec<_>>().join(" ")
14-
} else {
15-
"ls -ls".to_string()
16-
};
17-
18-
//let config_path:PathBuf = "./ctrl_config.yml".parse().unwrap();
19-
let config_path:PathBuf = "./config.prod.yml".parse().unwrap();
23+
let cli = Cli::parse();
24+
if cli.command.is_empty() {
25+
bail!("no command could be sent to MQTT");
26+
}
27+
let command = cli.command.join(" ");
2028

2129
let is_terminal = std::io::stdout().is_terminal();
2230

2331
tracing_subscriber::fmt().with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::from("debug")),)
2432
.with_ansi(is_terminal).init();
2533

26-
let config = mproxy::config::CtrlConfig::new(config_path).unwrap();
34+
let config = mproxy::config::CtrlConfig::new(cli.config).unwrap();
2735

2836
let mqtt_url = format!("{}?client_id={}", &config.server, &config.client_id);
2937
let mut options = MqttOptions::parse_url(&mqtt_url).unwrap();
@@ -62,4 +70,26 @@ async fn main() -> anyhow::Result<()> {
6270
tokio::signal::ctrl_c().await?;
6371

6472
Ok(())
73+
}
74+
75+
#[cfg(test)]
76+
mod test{
77+
78+
use clap::Parser;
79+
use crate::Cli;
80+
81+
const APP_NAME:&str = mproxy::config::CTRL_APP_NAME;
82+
#[test]
83+
fn test_cli_01() {
84+
85+
let config = Cli::parse_from([APP_NAME,"--config=config", "ls", "pwd"]);
86+
println!("{config:?}");
87+
88+
let config = Cli::parse_from([APP_NAME, "-c","config.yaml", "ls", "pwd"]);
89+
println!("{config:?}");
90+
91+
let config = Cli::parse_from([APP_NAME, "-c","config.yaml"]);
92+
println!("{config:?}");
93+
94+
}
6595
}

agent/src/config.rs

+32-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use anyhow::bail;
2-
use etcetera::BaseStrategy;
1+
use std::env;
2+
use anyhow::{bail, Context};
33
use serde::{Deserialize, Serialize};
44
use std::path::PathBuf;
55
use tracing::info;
@@ -18,7 +18,11 @@ pub struct Config {
1818

1919
impl Config {
2020
pub fn new(config_path: Option<PathBuf>) -> anyhow::Result<Self> {
21-
let config_path = config_path.unwrap_or_else(|| Self::get_default_config_path());
21+
let config_path = if let Some(config_path)= config_path {
22+
config_path
23+
} else {
24+
Self::get_default_config_path()?
25+
};
2226
if !config_path.is_file() {
2327
bail!("config file not found: {:?}", config_path);
2428
}
@@ -28,17 +32,12 @@ impl Config {
2832
Ok(config)
2933
}
3034

31-
fn get_default_config_path() -> PathBuf {
32-
let path = etcetera::choose_base_strategy()
33-
.unwrap()
34-
.config_dir()
35-
.join(APP_NAME);
36-
if !path.exists() {
37-
std::fs::create_dir_all(&path).unwrap();
38-
}
39-
path
35+
fn get_default_config_path() -> anyhow::Result<PathBuf> {
36+
let path = get_exec_path()?;
37+
Ok(path.join(format!("{APP_NAME}.yml")))
4038
}
4139

40+
4241
pub fn get_command_topic(&self) -> String {
4342
self.command_topic.clone().unwrap_or_else(||format!("cmd/{}", self.client_id))
4443

@@ -48,6 +47,8 @@ impl Config {
4847
}
4948
}
5049

50+
pub const CTRL_APP_NAME: &str = "mpublish";
51+
5152

5253
#[derive(Serialize, Deserialize, Debug)]
5354
pub struct CtrlConfig {
@@ -60,16 +61,26 @@ pub struct CtrlConfig {
6061
subscribe_command_topic: Option<String>,
6162
}
6263
impl CtrlConfig {
63-
pub fn new(config_path:PathBuf) -> anyhow::Result<Self> {
64+
pub fn new(config_path:Option<PathBuf>) -> anyhow::Result<Self> {
65+
let config_path = if let Some(config_path)= config_path {
66+
config_path
67+
} else {
68+
Self::get_default_config_path()?
69+
};
6470
if !config_path.is_file() {
6571
bail!("config file not found: {:?}", config_path);
6672
}
67-
info!("load config from {:?}", config_path);
73+
info!("load ctrl config from {:?}", config_path);
6874
let config = std::fs::read_to_string(config_path)?;
6975
let config: Self = serde_yml::from_str(&config)?;
7076
Ok(config)
7177
}
7278

79+
fn get_default_config_path() -> anyhow::Result<PathBuf> {
80+
let path = get_exec_path()?;
81+
Ok(path.join(format!("{CTRL_APP_NAME}.yml")))
82+
}
83+
7384
pub fn get_publish_command_topic(&self) -> String {
7485
self.publish_command_topic.clone().unwrap_or_else(||format!("cmd/{}", self.subscribe_client_id))
7586

@@ -81,6 +92,13 @@ impl CtrlConfig {
8192

8293

8394

95+
fn get_exec_path() -> anyhow::Result<PathBuf>{
96+
let path = env::current_exe().with_context(||"can not get exe path")?;
97+
if let Some(path) = path.parent() {
98+
return Ok(path.to_path_buf())
99+
}
100+
bail!("can not get current exe path");
101+
}
84102

85103
#[cfg(test)]
86104
mod test {

0 commit comments

Comments
 (0)