mirror of https://github.com/telemt/telemt.git
Add multi-destination logging: syslog and file support
Implement logging infrastructure for non-systemd platforms: - Add src/logging.rs with syslog and file logging support - New CLI flags: --syslog, --log-file, --log-file-daily - Syslog uses libc directly with LOG_DAEMON facility - File logging via tracing-appender with optional daily rotation Update service scripts: - OpenRC and FreeBSD rc.d now use --syslog by default - Ensures logs are captured on platforms without journald Default (stderr) behavior unchanged for systemd compatibility. Log destination is selected at startup based on CLI flags. Signed-off-by: Vladimir Krivopalov <argenet@yandex.ru>
This commit is contained in:
parent
909714af31
commit
95685adba7
|
|
@ -2822,6 +2822,7 @@ dependencies = [
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml",
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
"tracing-appender",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"url",
|
"url",
|
||||||
"webpki-roots",
|
"webpki-roots",
|
||||||
|
|
@ -3148,6 +3149,18 @@ dependencies = [
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-appender"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
"time",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-attributes"
|
name = "tracing-attributes"
|
||||||
version = "0.1.31"
|
version = "0.1.31"
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ bytes = "1.9"
|
||||||
thiserror = "2.0"
|
thiserror = "2.0"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||||
|
tracing-appender = "0.2"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
dashmap = "6.1"
|
dashmap = "6.1"
|
||||||
arc-swap = "1.7"
|
arc-swap = "1.7"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,291 @@
|
||||||
|
//! Logging configuration for telemt.
|
||||||
|
//!
|
||||||
|
//! Supports multiple log destinations:
|
||||||
|
//! - stderr (default, works with systemd journald)
|
||||||
|
//! - syslog (Unix only, for traditional init systems)
|
||||||
|
//! - file (with optional rotation)
|
||||||
|
|
||||||
|
#![allow(dead_code)] // Infrastructure module - used via CLI flags
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
|
use tracing_subscriber::{EnvFilter, fmt, reload};
|
||||||
|
|
||||||
|
/// Log destination configuration.
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub enum LogDestination {
|
||||||
|
/// Log to stderr (default, captured by systemd journald).
|
||||||
|
#[default]
|
||||||
|
Stderr,
|
||||||
|
/// Log to syslog (Unix only).
|
||||||
|
#[cfg(unix)]
|
||||||
|
Syslog,
|
||||||
|
/// Log to a file with optional rotation.
|
||||||
|
File {
|
||||||
|
path: String,
|
||||||
|
/// Rotate daily if true.
|
||||||
|
rotate_daily: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Logging options parsed from CLI/config.
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct LoggingOptions {
|
||||||
|
/// Where to send logs.
|
||||||
|
pub destination: LogDestination,
|
||||||
|
/// Disable ANSI colors.
|
||||||
|
pub disable_colors: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Guard that must be held to keep file logging active.
|
||||||
|
/// When dropped, flushes and closes log files.
|
||||||
|
pub struct LoggingGuard {
|
||||||
|
_guard: Option<tracing_appender::non_blocking::WorkerGuard>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoggingGuard {
|
||||||
|
fn new(guard: Option<tracing_appender::non_blocking::WorkerGuard>) -> Self {
|
||||||
|
Self { _guard: guard }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a no-op guard for stderr/syslog logging.
|
||||||
|
pub fn noop() -> Self {
|
||||||
|
Self { _guard: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialize the tracing subscriber with the specified options.
|
||||||
|
///
|
||||||
|
/// Returns a reload handle for dynamic log level changes and a guard
|
||||||
|
/// that must be kept alive for file logging.
|
||||||
|
pub fn init_logging(
|
||||||
|
opts: &LoggingOptions,
|
||||||
|
initial_filter: &str,
|
||||||
|
) -> (reload::Handle<EnvFilter, impl tracing::Subscriber + Send + Sync>, LoggingGuard) {
|
||||||
|
let (filter_layer, filter_handle) = reload::Layer::new(EnvFilter::new(initial_filter));
|
||||||
|
|
||||||
|
match &opts.destination {
|
||||||
|
LogDestination::Stderr => {
|
||||||
|
let fmt_layer = fmt::Layer::default()
|
||||||
|
.with_ansi(!opts.disable_colors)
|
||||||
|
.with_target(true);
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
(filter_handle, LoggingGuard::noop())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
LogDestination::Syslog => {
|
||||||
|
// Use a custom fmt layer that writes to syslog
|
||||||
|
let fmt_layer = fmt::Layer::default()
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_target(true)
|
||||||
|
.with_writer(SyslogWriter::new);
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
(filter_handle, LoggingGuard::noop())
|
||||||
|
}
|
||||||
|
|
||||||
|
LogDestination::File { path, rotate_daily } => {
|
||||||
|
let (non_blocking, guard) = if *rotate_daily {
|
||||||
|
// Extract directory and filename prefix
|
||||||
|
let path = Path::new(path);
|
||||||
|
let dir = path.parent().unwrap_or(Path::new("/var/log"));
|
||||||
|
let prefix = path.file_name()
|
||||||
|
.and_then(|s| s.to_str())
|
||||||
|
.unwrap_or("telemt");
|
||||||
|
|
||||||
|
let file_appender = tracing_appender::rolling::daily(dir, prefix);
|
||||||
|
tracing_appender::non_blocking(file_appender)
|
||||||
|
} else {
|
||||||
|
let file = std::fs::OpenOptions::new()
|
||||||
|
.create(true)
|
||||||
|
.append(true)
|
||||||
|
.open(path)
|
||||||
|
.expect("Failed to open log file");
|
||||||
|
tracing_appender::non_blocking(file)
|
||||||
|
};
|
||||||
|
|
||||||
|
let fmt_layer = fmt::Layer::default()
|
||||||
|
.with_ansi(false)
|
||||||
|
.with_target(true)
|
||||||
|
.with_writer(non_blocking);
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
(filter_handle, LoggingGuard::new(Some(guard)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Syslog writer for tracing.
|
||||||
|
#[cfg(unix)]
|
||||||
|
struct SyslogWriter {
|
||||||
|
_private: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl SyslogWriter {
|
||||||
|
fn new() -> Self {
|
||||||
|
// Open syslog connection on first use
|
||||||
|
static INIT: std::sync::Once = std::sync::Once::new();
|
||||||
|
INIT.call_once(|| {
|
||||||
|
unsafe {
|
||||||
|
// Open syslog with ident "telemt", LOG_PID, LOG_DAEMON facility
|
||||||
|
let ident = b"telemt\0".as_ptr() as *const libc::c_char;
|
||||||
|
libc::openlog(ident, libc::LOG_PID | libc::LOG_NDELAY, libc::LOG_DAEMON);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self { _private: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl std::io::Write for SyslogWriter {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||||
|
// Convert to C string, stripping newlines
|
||||||
|
let msg = String::from_utf8_lossy(buf);
|
||||||
|
let msg = msg.trim_end();
|
||||||
|
|
||||||
|
if msg.is_empty() {
|
||||||
|
return Ok(buf.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine priority based on log level in the message
|
||||||
|
let priority = if msg.contains(" ERROR ") || msg.contains(" error ") {
|
||||||
|
libc::LOG_ERR
|
||||||
|
} else if msg.contains(" WARN ") || msg.contains(" warn ") {
|
||||||
|
libc::LOG_WARNING
|
||||||
|
} else if msg.contains(" INFO ") || msg.contains(" info ") {
|
||||||
|
libc::LOG_INFO
|
||||||
|
} else if msg.contains(" DEBUG ") || msg.contains(" debug ") {
|
||||||
|
libc::LOG_DEBUG
|
||||||
|
} else {
|
||||||
|
libc::LOG_INFO
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write to syslog
|
||||||
|
let c_msg = std::ffi::CString::new(msg.as_bytes())
|
||||||
|
.unwrap_or_else(|_| std::ffi::CString::new("(invalid utf8)").unwrap());
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
libc::syslog(priority, b"%s\0".as_ptr() as *const libc::c_char, c_msg.as_ptr());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(buf.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> std::io::Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for SyslogWriter {
|
||||||
|
type Writer = SyslogWriter;
|
||||||
|
|
||||||
|
fn make_writer(&'a self) -> Self::Writer {
|
||||||
|
SyslogWriter::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse log destination from CLI arguments.
|
||||||
|
pub fn parse_log_destination(args: &[String]) -> LogDestination {
|
||||||
|
let mut i = 0;
|
||||||
|
while i < args.len() {
|
||||||
|
match args[i].as_str() {
|
||||||
|
#[cfg(unix)]
|
||||||
|
"--syslog" => {
|
||||||
|
return LogDestination::Syslog;
|
||||||
|
}
|
||||||
|
"--log-file" => {
|
||||||
|
i += 1;
|
||||||
|
if i < args.len() {
|
||||||
|
return LogDestination::File {
|
||||||
|
path: args[i].clone(),
|
||||||
|
rotate_daily: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s if s.starts_with("--log-file=") => {
|
||||||
|
return LogDestination::File {
|
||||||
|
path: s.trim_start_matches("--log-file=").to_string(),
|
||||||
|
rotate_daily: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"--log-file-daily" => {
|
||||||
|
i += 1;
|
||||||
|
if i < args.len() {
|
||||||
|
return LogDestination::File {
|
||||||
|
path: args[i].clone(),
|
||||||
|
rotate_daily: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s if s.starts_with("--log-file-daily=") => {
|
||||||
|
return LogDestination::File {
|
||||||
|
path: s.trim_start_matches("--log-file-daily=").to_string(),
|
||||||
|
rotate_daily: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
LogDestination::Stderr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_log_destination_default() {
|
||||||
|
let args: Vec<String> = vec![];
|
||||||
|
assert!(matches!(parse_log_destination(&args), LogDestination::Stderr));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_log_destination_file() {
|
||||||
|
let args = vec!["--log-file".to_string(), "/var/log/telemt.log".to_string()];
|
||||||
|
match parse_log_destination(&args) {
|
||||||
|
LogDestination::File { path, rotate_daily } => {
|
||||||
|
assert_eq!(path, "/var/log/telemt.log");
|
||||||
|
assert!(!rotate_daily);
|
||||||
|
}
|
||||||
|
_ => panic!("Expected File destination"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_log_destination_file_daily() {
|
||||||
|
let args = vec!["--log-file-daily=/var/log/telemt".to_string()];
|
||||||
|
match parse_log_destination(&args) {
|
||||||
|
LogDestination::File { path, rotate_daily } => {
|
||||||
|
assert_eq!(path, "/var/log/telemt");
|
||||||
|
assert!(rotate_daily);
|
||||||
|
}
|
||||||
|
_ => panic!("Expected File destination"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
#[test]
|
||||||
|
fn test_parse_log_destination_syslog() {
|
||||||
|
let args = vec!["--syslog".to_string()];
|
||||||
|
assert!(matches!(parse_log_destination(&args), LogDestination::Syslog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use crate::cli;
|
use crate::cli;
|
||||||
use crate::config::ProxyConfig;
|
use crate::config::ProxyConfig;
|
||||||
|
use crate::logging::LogDestination;
|
||||||
use crate::transport::middle_proxy::{
|
use crate::transport::middle_proxy::{
|
||||||
ProxyConfigData, fetch_proxy_config_with_raw, load_proxy_config_cache, save_proxy_config_cache,
|
ProxyConfigData, fetch_proxy_config_with_raw, load_proxy_config_cache, save_proxy_config_cache,
|
||||||
};
|
};
|
||||||
|
|
@ -31,6 +32,7 @@ pub(crate) struct CliArgs {
|
||||||
pub data_path: Option<PathBuf>,
|
pub data_path: Option<PathBuf>,
|
||||||
pub silent: bool,
|
pub silent: bool,
|
||||||
pub log_level: Option<String>,
|
pub log_level: Option<String>,
|
||||||
|
pub log_destination: LogDestination,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_cli() -> CliArgs {
|
pub(crate) fn parse_cli() -> CliArgs {
|
||||||
|
|
@ -41,6 +43,9 @@ pub(crate) fn parse_cli() -> CliArgs {
|
||||||
|
|
||||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||||
|
|
||||||
|
// Parse log destination
|
||||||
|
let log_destination = crate::logging::parse_log_destination(&args);
|
||||||
|
|
||||||
// Check for --init first (handled before tokio)
|
// Check for --init first (handled before tokio)
|
||||||
if let Some(init_opts) = cli::parse_init_args(&args) {
|
if let Some(init_opts) = cli::parse_init_args(&args) {
|
||||||
if let Err(e) = cli::run_init(init_opts) {
|
if let Err(e) = cli::run_init(init_opts) {
|
||||||
|
|
@ -124,6 +129,7 @@ pub(crate) fn parse_cli() -> CliArgs {
|
||||||
data_path,
|
data_path,
|
||||||
silent,
|
silent,
|
||||||
log_level,
|
log_level,
|
||||||
|
log_destination,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -147,6 +153,12 @@ fn print_help() {
|
||||||
eprintln!(" --help, -h Show this help");
|
eprintln!(" --help, -h Show this help");
|
||||||
eprintln!(" --version, -V Show version");
|
eprintln!(" --version, -V Show version");
|
||||||
eprintln!();
|
eprintln!();
|
||||||
|
eprintln!("Logging options:");
|
||||||
|
eprintln!(" --log-file <PATH> Log to file (default: stderr)");
|
||||||
|
eprintln!(" --log-file-daily <PATH> Log to file with daily rotation");
|
||||||
|
#[cfg(unix)]
|
||||||
|
eprintln!(" --syslog Log to syslog (Unix only)");
|
||||||
|
eprintln!();
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
eprintln!("Daemon options (Unix only):");
|
eprintln!("Daemon options (Unix only):");
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ async fn run_inner(
|
||||||
let data_path = cli_args.data_path;
|
let data_path = cli_args.data_path;
|
||||||
let cli_silent = cli_args.silent;
|
let cli_silent = cli_args.silent;
|
||||||
let cli_log_level = cli_args.log_level;
|
let cli_log_level = cli_args.log_level;
|
||||||
|
let log_destination = cli_args.log_destination;
|
||||||
let startup_cwd = match std::env::current_dir() {
|
let startup_cwd = match std::env::current_dir() {
|
||||||
Ok(cwd) => cwd,
|
Ok(cwd) => cwd,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -213,17 +214,43 @@ async fn run_inner(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Configure color output based on config
|
// Initialize logging based on destination
|
||||||
let fmt_layer = if config.general.disable_colors {
|
let _logging_guard: Option<crate::logging::LoggingGuard>;
|
||||||
fmt::Layer::default().with_ansi(false)
|
match log_destination {
|
||||||
} else {
|
crate::logging::LogDestination::Stderr => {
|
||||||
fmt::Layer::default().with_ansi(true)
|
// Default: log to stderr (works with systemd journald)
|
||||||
};
|
let fmt_layer = if config.general.disable_colors {
|
||||||
|
fmt::Layer::default().with_ansi(false)
|
||||||
|
} else {
|
||||||
|
fmt::Layer::default().with_ansi(true)
|
||||||
|
};
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(fmt_layer)
|
||||||
|
.init();
|
||||||
|
_logging_guard = None;
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
crate::logging::LogDestination::Syslog => {
|
||||||
|
// Syslog: for OpenRC/FreeBSD
|
||||||
|
let logging_opts = crate::logging::LoggingOptions {
|
||||||
|
destination: log_destination,
|
||||||
|
disable_colors: true,
|
||||||
|
};
|
||||||
|
let (_, guard) = crate::logging::init_logging(&logging_opts, "info");
|
||||||
|
_logging_guard = Some(guard);
|
||||||
|
}
|
||||||
|
crate::logging::LogDestination::File { .. } => {
|
||||||
|
// File logging with optional rotation
|
||||||
|
let logging_opts = crate::logging::LoggingOptions {
|
||||||
|
destination: log_destination,
|
||||||
|
disable_colors: true,
|
||||||
|
};
|
||||||
|
let (_, guard) = crate::logging::init_logging(&logging_opts, "info");
|
||||||
|
_logging_guard = Some(guard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tracing_subscriber::registry()
|
|
||||||
.with(filter_layer)
|
|
||||||
.with(fmt_layer)
|
|
||||||
.init();
|
|
||||||
startup_tracker
|
startup_tracker
|
||||||
.complete_component(
|
.complete_component(
|
||||||
COMPONENT_TRACING_INIT,
|
COMPONENT_TRACING_INIT,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ mod crypto;
|
||||||
mod daemon;
|
mod daemon;
|
||||||
mod error;
|
mod error;
|
||||||
mod ip_tracker;
|
mod ip_tracker;
|
||||||
|
mod logging;
|
||||||
mod service;
|
mod service;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "tests/ip_tracker_hotpath_adversarial_tests.rs"]
|
#[path = "tests/ip_tracker_hotpath_adversarial_tests.rs"]
|
||||||
|
|
|
||||||
|
|
@ -181,18 +181,20 @@ r#"#!/sbin/openrc-run
|
||||||
|
|
||||||
description="{description}"
|
description="{description}"
|
||||||
command="{exe}"
|
command="{exe}"
|
||||||
command_args="--daemon --pid-file {pid_file} {config}"
|
command_args="--daemon --syslog --pid-file {pid_file} {config}"
|
||||||
command_user="{user}:{group}"
|
command_user="{user}:{group}"
|
||||||
pidfile="{pid_file}"
|
pidfile="{pid_file}"
|
||||||
|
|
||||||
depend() {{
|
depend() {{
|
||||||
need net
|
need net
|
||||||
|
use logger
|
||||||
after firewall
|
after firewall
|
||||||
}}
|
}}
|
||||||
|
|
||||||
start_pre() {{
|
start_pre() {{
|
||||||
checkpath --directory --owner {user}:{group} --mode 0755 /var/run
|
checkpath --directory --owner {user}:{group} --mode 0755 /var/run
|
||||||
checkpath --directory --owner {user}:{group} --mode 0755 /var/lib/telemt
|
checkpath --directory --owner {user}:{group} --mode 0755 /var/lib/telemt
|
||||||
|
checkpath --directory --owner {user}:{group} --mode 0755 /var/log/telemt
|
||||||
}}
|
}}
|
||||||
|
|
||||||
reload() {{
|
reload() {{
|
||||||
|
|
@ -246,7 +248,7 @@ load_rc_config $name
|
||||||
|
|
||||||
pidfile="${{telemt_pidfile}}"
|
pidfile="${{telemt_pidfile}}"
|
||||||
command="{exe}"
|
command="{exe}"
|
||||||
command_args="--daemon --pid-file ${{telemt_pidfile}} ${{telemt_config}}"
|
command_args="--daemon --syslog --pid-file ${{telemt_pidfile}} ${{telemt_config}}"
|
||||||
|
|
||||||
start_precmd="telemt_prestart"
|
start_precmd="telemt_prestart"
|
||||||
reload_cmd="telemt_reload"
|
reload_cmd="telemt_reload"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue