diff --git a/src/uu/tail/src/tail.rs b/src/uu/tail/src/tail.rs index edac4b151cb..a48da6b315e 100644 --- a/src/uu/tail/src/tail.rs +++ b/src/uu/tail/src/tail.rs @@ -65,13 +65,15 @@ fn uu_tail(settings: &Settings) -> UResult<()> { // Add `path` and `reader` to `files` map if `--follow` is selected. for input in &settings.inputs.clone() { match input.kind() { - InputKind::File(path) if cfg!(not(unix)) || path != &PathBuf::from(text::DEV_STDIN) => { - tail_file(settings, &mut printer, input, path, &mut observer, 0)?; + InputKind::Stdin => { + tail_stdin(settings, &mut printer, input, &mut observer)?; } - // File points to /dev/stdin here - InputKind::File(_) | InputKind::Stdin => { + InputKind::File(path) if cfg!(unix) && path == &PathBuf::from(text::DEV_STDIN) => { tail_stdin(settings, &mut printer, input, &mut observer)?; } + InputKind::File(path) => { + tail_file(settings, &mut printer, input, path, &mut observer, 0)?; + } } } @@ -85,7 +87,7 @@ fn uu_tail(settings: &Settings) -> UResult<()> { the input file is not a FIFO, pipe, or regular file, it is unspecified whether or not the -f option shall be ignored. */ - if !settings.has_only_stdin() { + if !settings.has_only_stdin() || settings.pid != 0 { follow::follow(observer, settings)?; } } diff --git a/tests/by-util/test_tail.rs b/tests/by-util/test_tail.rs index 4c7c52c7c18..885e50ad3c0 100644 --- a/tests/by-util/test_tail.rs +++ b/tests/by-util/test_tail.rs @@ -6,6 +6,7 @@ // spell-checker:ignore (ToDO) abcdefghijklmnopqrstuvwxyz efghijklmnopqrstuvwxyz vwxyz emptyfile file siette ocho nueve diez MULT // spell-checker:ignore (libs) kqueue // spell-checker:ignore (jargon) tailable untailable datasame runneradmin tmpi +// spell-checker:ignore (cmd) taskkill #![allow( clippy::unicode_not_nfc, clippy::cast_lossless, @@ -4822,3 +4823,61 @@ fn test_obsolete_encoding_windows() { .stderr_is("tail: bad argument encoding: '-�b'\n") .code_is(1); } + +#[test] +#[cfg(not(target_vendor = "apple"))] // FIXME: for currently not working platforms +fn test_following_with_pid() { + use std::process::Command; + + let ts = TestScenario::new(util_name!()); + + #[cfg(not(windows))] + let mut sleep_command = Command::new("sleep") + .arg("999d") + .spawn() + .expect("failed to start sleep command"); + #[cfg(windows)] + let mut sleep_command = Command::new("powershell") + .arg("-Command") + .arg("Start-Sleep -Seconds 999") + .spawn() + .expect("failed to start sleep command"); + + let sleep_pid = sleep_command.id(); + + let at = &ts.fixtures; + at.touch("f"); + // when -f is specified, tail should die after + // the pid from --pid also dies + let mut child = ts + .ucmd() + .args(&[ + "--pid", + &sleep_pid.to_string(), + "-f", + at.plus("f").to_str().unwrap(), + ]) + .stderr_to_stdout() + .run_no_wait(); + child.make_assertion_with_delay(2000).is_alive(); + + #[cfg(not(windows))] + Command::new("kill") + .arg("-9") + .arg(sleep_pid.to_string()) + .output() + .expect("failed to kill sleep command"); + #[cfg(windows)] + Command::new("taskkill") + .arg("/PID") + .arg(sleep_pid.to_string()) + .arg("/F") + .output() + .expect("failed to kill sleep command"); + + let _ = sleep_command.wait(); + + child.make_assertion_with_delay(2000).is_not_alive(); + + child.kill(); +}