33

Can less follow (by pressing F) a piped input (similarly to a file)? For a file that is being written to, the command

less <file>

will follow the file when pressing F.

But if I have a command that pipes output directly into less, like this

command | less

pressing F will do nothing.

So it looks like pipes cannot be followed like files can? Or maybe it has to do with command also writing to STDERR? The effect I'm trying to achieve is always see the latest output of the command: just like keeping PageDown pressed!

A related remark holds for G (go to end): when piping directly to less, it won't work.

haelix
  • 592

4 Answers4

29

Pressing F or G makes less try to reach input EOF. If the input is a pipe, less hangs until the pipe is closed on the other side (and not "does nothing").

This can be worked around by saving the command output to a temporary file in the background, and then by using it as input for less:

command > /tmp/x &
less +F /tmp/x; kill %; rm /tmp/x

There is no option to do this in less only; however, I admit it would be useful.

mik
  • 1,342
  • If the input is a pipe, less hangs until the pipe is closed on the other side. That's kind of misleading statement. What happens is that less calls read in a blocking mode, waiting for new data or or pipe's closure. – Piotr Dobrogost Dec 11 '14 at 11:24
  • 3
    After pressing F or G on pipe input less not only does a blocking read, but does it in a loop waiting for EOF. And an EOF on a pipe happens only if its other side is closed. – mik Feb 12 '15 at 22:29
  • 3
    If less would update screen in that loop, there would not be a problem. Blocking read has little to do with this issue. – mik Feb 12 '15 at 22:46
  • If the input is a pipe, less hangs until the pipe is closed on the other side. That's not my observation. For example echo foo |less +F results in less displaying Waiting for data... (interrupt to abort), so it does not hang until the pipe is closed, but until an interrupt is received. – Flow Jun 23 '16 at 12:03
  • 1
    @Flow this is not a hang the question was about, but merely a wait which is expected in this situation - a wait for more data in the file when EOF is reached (which will not happen for a closed pipe, by the way), or for an interrupt to exit the follow mode – mik Jun 27 '16 at 09:21
  • @mik If less would update screen in that loop, there would not be a problem. Blocking read has little to do with this issue. If the read were blocking then less wouldn't be able to update screen unless the read was in a different thread, would it? – Piotr Dobrogost Jan 19 '17 at 10:10
  • 1
    @PiotrDobrogost with blocking read less wouldn't be able to update screen, if there is no data; when some data appear, blocking read will return it, and less would be able to update screen without a separate thread – mik Jan 19 '17 at 13:11
  • @mik And here, we are interested in the no data case. Earlier you wrote After pressing F or G on pipe input less not only does a blocking read, but does it in a loop waiting for EOF. My point is that even if there was no waiting for EOF less would block on read after it had read all data from pipe. – Piotr Dobrogost Jan 19 '17 at 13:36
  • 1
    @PiotrDobrogost yes, it would block waiting for new data or EOF, but my point is that the screen does not need to be updated during this waiting (just because there is no new data) – mik Jan 21 '17 at 11:44
10

Can less follow (by pressing F) a piped input (similarly to a file)?

Yes, starting with version 474.

Related: Is there any way to exit “less” follow mode without stopping other processes in pipe?

For reference, the issue with F not working with pipes has reference number 300 on the list of known bugs and is titled The F command does not work on piped input.


A related remark holds for G (go to end): when piping directly to less, it won't work.

It works starting from version 466. Citing from release notes for this version:

New command ESC-G goes to end of currently buffered data in a pipe

  • The ESC-G command was introduced in version 466, released on 23 Aug 2014. – mik Feb 12 '15 at 23:02
  • @mik Looks like an error in release notes for version 471 then. Thanks, fixed. – Piotr Dobrogost Feb 12 '15 at 23:11
  • Not an error, they just list the changes incrementally since a stable release, version 458 in this case. However, there is no stable release with the ESC-G command. – mik Feb 12 '15 at 23:56
  • The ESC-G command is now in a stable release (481): "16 Oct 2015 less-481 has been released for general use". – mik Feb 18 '16 at 16:41
  • Update: Regarding the F command on pipes, this is also fixed in less-474. Instead of seeking to EOF, the F command seeks to the end of buffered input and starts reading there. However it's not really usable because when you hit ctrl-C to stop the F command, it kills the process producing output. I'm not sure how to fix that. – Mark Nudelman, maintainer of less – Piotr Dobrogost May 08 '17 at 13:57
  • @mik I forwarded your suggestion to Mark. Btw, why would less call fork() and exec() and how do you know it does? – Piotr Dobrogost Jul 31 '17 at 12:56
  • @mik I know it is but why would less need to spawn new processes? – Piotr Dobrogost Jul 31 '17 at 13:20
  • @ Piotr, you are right. The other process is not invoked by less. I have deleted my useless comments. Instead less could do setpgid(0, 0); to create a new process group for itself, what makes signals not to propagate to other process groups. – mik Jul 31 '17 at 13:37
  • @mik I'm wondering if less creating its own process group could lead to any problematic changes in other places… – Piotr Dobrogost Jul 31 '17 at 17:10
  • @ Piotr, probably it will affect shell job control, like sending less into background. – mik Jul 31 '17 at 18:05
  • IMHO a best solution for less developer is to use another another key sequence to exit follow mode (by using select with a timeout on read from the terminal). – mik Aug 01 '17 at 07:26
3

From the less man page

[Keyboard] COMMANDS [...]

   F      Scroll  forward, and keep trying to read when the end of file is reached.  Normally this command would be used when already
          at the end of the file.  It is a way to monitor the tail of a file which is growing while it is being viewed.  (The  behav‐
          ior is similar to the "tail -f" command.)

so this should work, and it actually works for me.

wnrph
  • 1,444
2

For older versions of less (many distros still do not have v581 or later as default) you can use the F-key ("Follow") on a pipe in less as if you were performing less on a file directly by using this one-liner (no tmp files):

The problem is that pressing ctrl+c sends a SIGINT to all commands in the pipeline, aborting not only your less-follow, but your generating command as well. To work around this I usually put the generating command in a subshell and trap SIGINT there. Like this:

(trap '' SIGINT; command) | less

The parenthesis give you a subshell and trap with empty command '' is a special invocation that throws away the signal entirely within that subshell, without propagating it to the currently executing command. SIGINT is the ctrl+c signal. Now you can hit ctrl+c and only less will receive it, letting you use less on a pipe just like you would on a log-file or other growing file. Once you quit less (by pressing q) the pipeline is broken and the generating command gets sent a SIGPIPE, which almost always has the same effect as being sent a SIGINT, but the trap isn't set up to catch it.

Newer versions of less from v581 and onwards allow you to use ctrl+x in place of ctrl+c to abort the follow command (F-key).

  • 1
    Just to clarify: since version 581 (released on 18 Apr 2021 for general use) ctrl+X can be used to exit F mode. – mik Feb 04 '22 at 22:08
  • Thanks. Yes, newer versions of less have ctrl-X, though many machines are still running older versions of less. I will edit my answer to mention this. – 00prometheus Mar 19 '22 at 15:15
  • That's weird... ctrl+x doesn't cause exiting F mode when less is in pipe mode, but works fine when following a file, e.g. less --follow-name -BSb1024 +F /var/log/nginx/access.log <- ctrl+x work fine, (trap '' SIGINT; tail -n 100 -F /var/log/nginx/access.log -F) | less -S +F <- no reaction to ctrl+x at all. (Debian 12 + less v590) – Nik Feb 28 '24 at 19:36