feat: 添加守护进程(daemon)模式
- 实现 TCP Socket 守护进程,支持后台运行 - 添加 daemon 子命令:start/stop/status/logs - 添加 send 子命令:发送文本到守护进程播放 - 添加日志级别自动检测(INFO/WARN/ERROR) - 新日志格式:[时间戳] [级别] [PID] 消息 - 支持跨平台 ~/.config/tts/ 配置目录
This commit is contained in:
83
src/main.rs
83
src/main.rs
@@ -3,6 +3,46 @@ mod config;
|
||||
mod api;
|
||||
mod ui;
|
||||
mod tone;
|
||||
mod daemon;
|
||||
mod client;
|
||||
|
||||
/// 启动守护进程(后台运行)
|
||||
///
|
||||
/// 通过启动新进程来实现后台运行
|
||||
fn spawn_daemon_process(port: u16) -> Result<()> {
|
||||
// 获取当前可执行文件路径
|
||||
let exe_path = std::env::current_exe()
|
||||
.context("无法获取当前可执行文件路径")?;
|
||||
|
||||
// 启动新进程,执行 ttsd 命令
|
||||
// 使用 nohup 实现后台运行(Unix)
|
||||
#[cfg(unix)]
|
||||
{
|
||||
std::process::Command::new("nohup")
|
||||
.arg(&exe_path)
|
||||
.arg("ttsd")
|
||||
.arg("--port")
|
||||
.arg(port.to_string())
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.stdin(std::process::Stdio::null())
|
||||
.spawn()
|
||||
.context("无法启动守护进程")?;
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
std::process::Command::new("cmd")
|
||||
.args(["/C", "start", "", &exe_path.to_string_lossy(), "ttsd", "--port", &port.to_string()])
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.stdin(std::process::Stdio::null())
|
||||
.spawn()
|
||||
.context("无法启动守护进程")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
@@ -81,6 +121,49 @@ async fn run(cli: Cli) -> Result<()> {
|
||||
// 引导式配置初始化
|
||||
onboard().await
|
||||
}
|
||||
Some(Commands::Daemon(daemon_cmd)) => {
|
||||
// 处理守护进程命令
|
||||
match daemon_cmd.action {
|
||||
cli::DaemonAction::Start { port, daemonize } => {
|
||||
if daemonize {
|
||||
// 后台运行:启动新进程执行 tt sd 命令
|
||||
spawn_daemon_process(port)?;
|
||||
println!("守护进程已在后台启动");
|
||||
Ok(())
|
||||
} else {
|
||||
// 前台运行
|
||||
daemon::start_daemon(port).await
|
||||
}
|
||||
}
|
||||
cli::DaemonAction::Stop => {
|
||||
daemon::stop_daemon()
|
||||
}
|
||||
cli::DaemonAction::Status => {
|
||||
daemon::show_status()
|
||||
}
|
||||
cli::DaemonAction::Logs { lines } => {
|
||||
daemon::show_logs(lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Commands::DaemonMode { port }) => {
|
||||
// 守护进程模式(由 daemon start -d 自动调用)
|
||||
daemon::start_daemon(port).await
|
||||
}
|
||||
Some(Commands::Send { text, voice, format, style, port }) => {
|
||||
// 发送文本到守护进程
|
||||
client::send_to_daemon(
|
||||
&text,
|
||||
voice.as_deref(),
|
||||
format.as_deref(),
|
||||
style.as_deref(),
|
||||
port,
|
||||
)
|
||||
.await
|
||||
.map(|msg| {
|
||||
println!("{}", msg);
|
||||
})
|
||||
}
|
||||
// 没有子命令时,执行语音合成
|
||||
None => {
|
||||
// 检查参数组合
|
||||
|
||||
Reference in New Issue
Block a user