diff --git a/src/uu/tail/locales/en-US.ftl b/src/uu/tail/locales/en-US.ftl index 6f7383aa48a..6d434ae9862 100644 --- a/src/uu/tail/locales/en-US.ftl +++ b/src/uu/tail/locales/en-US.ftl @@ -6,6 +6,7 @@ tail-usage = tail [FLAG]... [FILE]... # Help messages tail-help-bytes = Number of bytes to print +tail-help-debug = indicate which --follow implementation is used tail-help-follow = Print the file as it grows tail-help-lines = Number of lines to print tail-help-pid = With -f, terminate after process ID, PID dies @@ -70,3 +71,7 @@ tail-giving-up-on-this-name = ; giving up on this name tail-stdin-header = standard input tail-no-files-remaining = no files remaining tail-become-inaccessible = has become inaccessible + +# Debug messages +tail-debug-using-notification-mode = using notification mode +tail-debug-using-polling-mode = using polling mode diff --git a/src/uu/tail/src/args.rs b/src/uu/tail/src/args.rs index d5159ab7a49..63bd2b0da01 100644 --- a/src/uu/tail/src/args.rs +++ b/src/uu/tail/src/args.rs @@ -38,6 +38,7 @@ pub mod options { pub const MAX_UNCHANGED_STATS: &str = "max-unchanged-stats"; pub const ARG_FILES: &str = "files"; pub const PRESUME_INPUT_PIPE: &str = "-presume-input-pipe"; // NOTE: three hyphens is correct + pub const DEBUG: &str = "debug"; } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -139,6 +140,7 @@ pub struct Settings { pub use_polling: bool, pub verbose: bool, pub presume_input_pipe: bool, + pub debug: bool, /// `FILE(s)` positional arguments pub inputs: Vec, } @@ -155,6 +157,7 @@ impl Default for Settings { use_polling: Default::default(), verbose: Default::default(), presume_input_pipe: Default::default(), + debug: Default::default(), inputs: Vec::default(), } } @@ -223,6 +226,7 @@ impl Settings { mode: FilterMode::from(matches)?, verbose: matches.get_flag(options::verbosity::VERBOSE), presume_input_pipe: matches.get_flag(options::PRESUME_INPUT_PIPE), + debug: matches.get_flag(options::DEBUG), ..Default::default() }; @@ -543,6 +547,12 @@ pub fn uu_app() -> Command { .overrides_with(options::FOLLOW_RETRY) .action(ArgAction::SetTrue), ) + .arg( + Arg::new(options::DEBUG) + .long(options::DEBUG) + .help(translate!("tail-help-debug")) + .action(ArgAction::SetTrue), + ) .arg( Arg::new(options::PRESUME_INPUT_PIPE) .long("presume-input-pipe") diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index 3a16f670b63..8782db36f74 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -72,6 +72,16 @@ fn uu_tail(settings: &Settings) -> UResult<()> { let mut observer = Observer::from(settings); observer.start(settings)?; + + // Print debug info about the follow implementation being used + if settings.debug && settings.follow.is_some() { + if observer.use_polling { + show_error!("{}", translate!("tail-debug-using-polling-mode")); + } else { + show_error!("{}", translate!("tail-debug-using-notification-mode")); + } + } + // Do an initial tail print of each path's content. // Add `path` and `reader` to `files` map if `--follow` is selected. for input in &settings.inputs.clone() { diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 3dd0ee0d2d4..390633704ac 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -5065,3 +5065,39 @@ fn test_follow_stdout_pipe_close() { child.close_stdout(); child.delay(2000).make_assertion().is_not_alive(); } + +#[test] +fn test_debug_flag_with_polling() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + at.touch("f"); + + let mut child = ts + .ucmd() + .args(&["--debug", "-f", "--use-polling", "f"]) + .run_no_wait(); + + child.make_assertion_with_delay(500).is_alive(); + child + .kill() + .make_assertion() + .with_all_output() + .stderr_contains("tail: using polling mode"); +} + +#[test] +#[cfg(target_os = "linux")] +fn test_debug_flag_with_inotify() { + let ts = TestScenario::new(util_name!()); + let at = &ts.fixtures; + at.touch("f"); + + let mut child = ts.ucmd().args(&["--debug", "-f", "f"]).run_no_wait(); + + child.make_assertion_with_delay(500).is_alive(); + child + .kill() + .make_assertion() + .with_all_output() + .stderr_contains("tail: using notification mode"); +}