From 952f04149f7ddd8203a2dcbc8578019af2df3c69 Mon Sep 17 00:00:00 2001 From: houseme Date: Wed, 9 Apr 2025 19:11:31 +0800 Subject: [PATCH] add notify systemd --- Cargo.toml | 2 +- rustfs/Cargo.toml | 5 ++++- rustfs/src/console.rs | 2 +- rustfs/src/main.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5a126ae34..9f1b721ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,7 +68,7 @@ humantime = "2.1.0" keyring = { version = "3.6.1", features = ["apple-native", "windows-native", "sync-secret-service"] } lock = { path = "./common/lock" } lazy_static = "1.5.0" -libsystemd = "0.7.0" +libsystemd = { version = "0.7" } local-ip-address = "0.6.3" matchit = "0.8.4" md-5 = "0.10.6" diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index 902e0053c..00c10bebd 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -43,7 +43,7 @@ http.workspace = true http-body.workspace = true iam = { path = "../iam" } jsonwebtoken = "9.3.0" -libsystemd = { workspace = true } +libsystemd = { workspace = true, optional = true } lock.workspace = true local-ip-address = { workspace = true } matchit = { workspace = true } @@ -86,6 +86,9 @@ tower-http.workspace = true url.workspace = true uuid = "1.15.1" +[target.'cfg(target_os = "linux")'.dependencies] +libsystemd = "0.7" + [build-dependencies] prost-build.workspace = true tonic-build.workspace = true diff --git a/rustfs/src/console.rs b/rustfs/src/console.rs index 6b3e507fd..1eff0e906 100644 --- a/rustfs/src/console.rs +++ b/rustfs/src/console.rs @@ -216,7 +216,7 @@ pub async fn start_static_file_server( let app = Router::new() .route("/license", get(license_handler)) .route("/config.json", get(config_handler)) - .nest_service("/", get(static_handler)); + .fallback_service(get(static_handler)); let local_addr: SocketAddr = addrs.parse().expect("Failed to parse socket address"); info!("WebUI: http://{}:{} http://127.0.0.1:{}", local_ip, local_addr.port(), local_addr.port()); info!(" RootUser: {}", access_key); diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index 4481525bb..bd6d66d06 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -53,6 +53,27 @@ use tracing::{debug, error, info, info_span, warn}; use tracing_error::ErrorLayer; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +#[cfg(target_os = "linux")] +fn notify_systemd(state: &str) { + use libsystemd::daemon::{notify, NotifyState}; + let notify_state = match state { + "ready" => NotifyState::Ready, + "stopping" => NotifyState::Stopping, + _ => return, + }; + + if let Err(e) = notify(false, &[notify_state]) { + error!("Failed to notify systemd: {}", e); + } else { + debug!("Successfully notified systemd: {}", state); + } +} + +#[cfg(not(target_os = "linux"))] +fn notify_systemd(state: &str) { + debug!("Systemd notifications are not available on this platform (state: {})", state); +} + #[allow(dead_code)] fn setup_tracing() { use tracing_subscriber::EnvFilter; @@ -260,6 +281,9 @@ async fn run(opt: config::Opt) -> Result<()> { None }; + // Create a oneshot channel to wait for the service to start + let (tx, rx) = tokio::sync::oneshot::channel(); + tokio::spawn(async move { let hyper_service = service.into_shared(); let hybrid_service = TowerToHyperService::new( @@ -272,6 +296,10 @@ async fn run(opt: config::Opt) -> Result<()> { let mut ctrl_c = std::pin::pin!(tokio::signal::ctrl_c()); let graceful = hyper_util::server::graceful::GracefulShutdown::new(); debug!("graceful initiated"); + + // Send a message to the main thread to indicate that the server has started + let _ = tx.send(()); + loop { debug!("waiting for SIGINT or SIGTERM has_tls_certs: {}", has_tls_certs); // Wait for a connection @@ -286,9 +314,12 @@ async fn run(opt: config::Opt) -> Result<()> { } } _ = ctrl_c.as_mut() => { + drop(listener); + eprintln!("Ctrl-C received, starting shutdown"); break; } }; + if has_tls_certs { debug!("TLS certificates found, starting with SIGINT"); let tls_socket = match tls_acceptor @@ -353,7 +384,7 @@ async fn run(opt: config::Opt) -> Result<()> { })?; debug!("init store success!"); - init_iam_sys(store.clone()).await.unwrap(); + init_iam_sys(store.clone()).await?; new_global_notification_sys(endpoint_pools.clone()).await.map_err(|err| { error!("new_global_notification_sys failed {:?}", &err); @@ -386,9 +417,15 @@ async fn run(opt: config::Opt) -> Result<()> { }); } + // Wait for the HTTP service to finish starting + if rx.await.is_ok() { + notify_systemd("ready"); + } + tokio::select! { _ = tokio::signal::ctrl_c() => { - + eprintln!("Ctrl-C received, starting shutdown"); + notify_systemd("stopping"); } }