coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Unexpected behavior of 'tail --follow=name' on special file via syml


From: Glenn Golden
Subject: Re: Unexpected behavior of 'tail --follow=name' on special file via symlink
Date: Tue, 31 Jan 2023 12:48:55 -0700

Pádraig Brady <P@draigBrady.com> [2023-01-30 21:27:50 +0000]:
> 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.

With the above patch (applied manually to coreutils 9.1 sources) the
'illegal seek' no longer occurs, but it also doesn't follow the new file:
There is no output at all after tail announces that it is "following new file." 

I did verify that the "new" instance of /dev/ttyMYDEV, when observed from
another independent process (via cat, less, more, tail, etc.) is indeed
sinking output from the device, as expected. But tail just isn't seeing it.

Also fiddled about with --sleep-interval=N (with several values of N) and
--retry as well, but no joy.

Btw -- I should have mentioned this in the original report -- I am also using
the "--lines=+0" option, in order to capture the first lines of output
when initially starting the tail process. Didn't think this was relevant,
but perhaps it is.

You might be able to re-create this situation on your local machine if
you happen to have some USB device lying around that spews anything
regularly to an ACM tty device.  You could then set up a udev rule like mine,
and that should in principle give you the analogous situation to test against.
(Fyi, on my setup, the kernel driver that claims the ACM device is "cdc_acm".)

- Glenn



reply via email to

[Prev in Thread] Current Thread [Next in Thread]