On 30/01/2023 20:04, Glenn Golden wrote:
Not sure if this is a bug report, a feature request, or just a case of wrong
expectation on my part regarding the behavior of "tail --follow=name" when
the target is a special file (via a symlink).  Perhaps what I'm trying to do
is unreasonable and shouldn't really be expected to work.

In any case, any suggestions as to how to accomplish the desired goal would be
appreciated, even if by entirely different means than using tail per se.

Detailed description follows; version info at the end.

Thanks,

- Glenn



============================================================================
Background:

  I'm working with a USB device that writes debug info to a /dev/ttyACM
  interface which I then wish to observe continuously using tail(1) with the
  --follow=name option.  It is desirable for the tail process to gracefully
  survive a reboot of the target USB device, so that upon reboot, tail will
  continue to display the device's "new" debug stream.

  To accomplish this, a udev rule is defined which creates a consistent
  symlink name pointing to the device's ACM interface (let's call that symlink
  "/dev/ttyMYDEV").  So, upon reboot of the target USB device, udev duly
  re-points /dev/ttyMYDEV to the appropriate (kernel-named) /dev/ttyACMn
  interface presented by the device when it reincarnates after its reboot.

  As far as I'm able to tell, the udev rule does seem to accomplish that
  symlink creation correctly.

----------------------------------------------------------------------------
Expectation:

  Given the above, my expectation was that

    $ tail --follow=name /dev/ttyMYDEV"

  would handle the above-described situation gracefully upon reboot of the
  target device, similar to its behavior when using --follow=name to follow
  an on-the-fly re-created logfile having the same name as the original but
  a new file descriptor (e.g. due to log rotation).

  In other words, what I expected to see was something like this:

$ tail --follow=name /dev/ttyMYDEV

    Debug output line 1
    Debug output line 2
          .
          .
          .
    Debug output line n
    Debug output line n+1
    Debug output line n+2

    (==> target USB device is rebooted here <==)

    tail: '/dev/ttyMYDEV' has been replaced;  following new file

    Debug output line 1         # First line of "new" debug output
    Debug output line 2         # Second line of "new" debug output
          .
          .
          .

----------------------------------------------------------------------------
Observed behavior:

  Instead of the above, what is actually observed is this:

    $ tail --follow=name /dev/ttyMYDEV

    Debug output line 1
    Debug output line 2
          .
          .
          .
    Debug output line n
    Debug output line n+1
    Debug output line n+2

    (==> target USB device is rebooted here <==)

    tail: '/dev/ttyMYDEV' has been replaced;  following new file
    tail: /dev/ttyMYDEV: cannot seek to offset 0: Illegal seek


So... is this an inevitable consequence of trying to follow an un-seekable
special file?  Or could it possibly be handled in some fancy way so as to
provide the desired behavior?

Thanks for the detailed info.
I think this is an oversight where that seek wasn't guarded
against operating only on regular files.

Is it possible for you to easily try:

diff --git a/src/tail.c b/src/tail.c
index 2244509dd..03061e8bf 100644
--- a/src/tail.c
+++ b/src/tail.c
@@ -1122,7 +1122,8 @@ recheck (struct File_spec *f, bool blocking)
     {
       /* Start at the beginning of the file.  */
       record_open_fd (f, fd, 0, &new_stats, (is_stdin ? -1 : blocking));
-      xlseek (fd, 0, SEEK_SET, pretty_name (f));
+      if (S_ISREG (new_stats.st_mode))
+        xlseek (fd, 0, SEEK_SET, pretty_name (f));
     }
 }

thanks,
Pádraig

Reply via email to