fix(windows): unify config/data dir and add service log file
config_dir() on Windows now returns data_dir() (ProgramData) so config, services.json, and log file are in the same place for both interactive and service contexts. Service mode writes logs to numa.log via env_logger pipe. Dashboard shows correct log path per OS.
This commit is contained in:
@@ -1153,14 +1153,11 @@ async function refresh() {
|
|||||||
const isWin = stats.data_dir && stats.data_dir.includes(':\\');
|
const isWin = stats.data_dir && stats.data_dir.includes(':\\');
|
||||||
const isMac = stats.data_dir && stats.data_dir.includes('/usr/local/');
|
const isMac = stats.data_dir && stats.data_dir.includes('/usr/local/');
|
||||||
const logsEl = document.getElementById('footerLogs');
|
const logsEl = document.getElementById('footerLogs');
|
||||||
if (isWin) {
|
logsEl.textContent = isWin
|
||||||
document.getElementById('footerLogsWrap').style.display = 'none';
|
? stats.data_dir + '\\numa.log'
|
||||||
} else {
|
: isMac ? '/usr/local/var/log/numa.log'
|
||||||
logsEl.textContent = isMac
|
|
||||||
? '/usr/local/var/log/numa.log'
|
|
||||||
: 'journalctl -u numa -f';
|
: 'journalctl -u numa -f';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// LAN status indicator
|
// LAN status indicator
|
||||||
const lanEl = document.getElementById('lanToggle');
|
const lanEl = document.getElementById('lanToggle');
|
||||||
@@ -1523,7 +1520,7 @@ setInterval(refresh, 2000);
|
|||||||
<div style="text-align:center;padding:0.8rem 0.8rem 0.4rem;font-family:var(--font-mono);font-size:0.68rem;color:var(--text-dim);line-height:1.8;">
|
<div style="text-align:center;padding:0.8rem 0.8rem 0.4rem;font-family:var(--font-mono);font-size:0.68rem;color:var(--text-dim);line-height:1.8;">
|
||||||
Config: <span id="footerConfig" style="user-select:all;color:var(--emerald);"></span>
|
Config: <span id="footerConfig" style="user-select:all;color:var(--emerald);"></span>
|
||||||
· Data: <span id="footerData" style="user-select:all;color:var(--emerald);"></span>
|
· Data: <span id="footerData" style="user-select:all;color:var(--emerald);"></span>
|
||||||
<span id="footerLogsWrap">· Logs: <span id="footerLogs" style="user-select:all;color:var(--emerald);"></span></span>
|
· Logs: <span id="footerLogs" style="user-select:all;color:var(--emerald);"></span>
|
||||||
<br>
|
<br>
|
||||||
Upstream: <span id="footerUpstream" style="user-select:all;color:var(--emerald);"></span>
|
Upstream: <span id="footerUpstream" style="user-select:all;color:var(--emerald);"></span>
|
||||||
· DNSSEC: <span id="footerDnssec" style="color:var(--text-dim);">—</span>
|
· DNSSEC: <span id="footerDnssec" style="color:var(--text-dim);">—</span>
|
||||||
|
|||||||
@@ -101,14 +101,11 @@ where
|
|||||||
/// Linux root daemon: /var/lib/numa (FHS) — falls back to /usr/local/var/numa
|
/// Linux root daemon: /var/lib/numa (FHS) — falls back to /usr/local/var/numa
|
||||||
/// if a pre-v0.10.1 install already lives there.
|
/// if a pre-v0.10.1 install already lives there.
|
||||||
/// macOS root daemon: /usr/local/var/numa (Homebrew prefix)
|
/// macOS root daemon: /usr/local/var/numa (Homebrew prefix)
|
||||||
/// Windows: %APPDATA%\numa
|
/// Windows: %PROGRAMDATA%\numa (same as data_dir — no per-user config on Windows)
|
||||||
pub fn config_dir() -> std::path::PathBuf {
|
pub fn config_dir() -> std::path::PathBuf {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
std::path::PathBuf::from(
|
data_dir()
|
||||||
std::env::var("APPDATA").unwrap_or_else(|_| "C:\\ProgramData".into()),
|
|
||||||
)
|
|
||||||
.join("numa")
|
|
||||||
}
|
}
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
{
|
{
|
||||||
|
|||||||
27
src/main.rs
27
src/main.rs
@@ -4,21 +4,32 @@ use numa::system_dns::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
fn main() -> numa::Result<()> {
|
fn main() -> numa::Result<()> {
|
||||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
|
|
||||||
.format_timestamp_millis()
|
|
||||||
.init();
|
|
||||||
|
|
||||||
// Handle CLI subcommands
|
// Handle CLI subcommands
|
||||||
let arg1 = std::env::args().nth(1).unwrap_or_default();
|
let arg1 = std::env::args().nth(1).unwrap_or_default();
|
||||||
match arg1.as_str() {
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
"--service" => {
|
if arg1 == "--service" {
|
||||||
// Entry point used by Windows SCM (`sc create … binPath="numa.exe --service"`).
|
// Running under SCM — stderr goes nowhere. Redirect logs to a file.
|
||||||
// Blocks until SCM sends Stop; never returns normally.
|
let log_path = numa::data_dir().join("numa.log");
|
||||||
|
let log_file = std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open(&log_path)
|
||||||
|
.expect("failed to open log file");
|
||||||
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
|
||||||
|
.format_timestamp_millis()
|
||||||
|
.target(env_logger::Target::Pipe(Box::new(log_file)))
|
||||||
|
.init();
|
||||||
numa::windows_service::run_as_service()
|
numa::windows_service::run_as_service()
|
||||||
.map_err(|e| format!("windows service dispatcher failed: {}", e))?;
|
.map_err(|e| format!("windows service dispatcher failed: {}", e))?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
|
||||||
|
.format_timestamp_millis()
|
||||||
|
.init();
|
||||||
|
|
||||||
|
match arg1.as_str() {
|
||||||
"install" => {
|
"install" => {
|
||||||
eprintln!("\x1b[1;38;2;192;98;58mNuma\x1b[0m — installing\n");
|
eprintln!("\x1b[1;38;2;192;98;58mNuma\x1b[0m — installing\n");
|
||||||
return install_service().map_err(|e| e.into());
|
return install_service().map_err(|e| e.into());
|
||||||
|
|||||||
Reference in New Issue
Block a user