17

I often pipe program output to less, e.g.

produce_output | less

This works great, until produce_output produces large amounts of output. If I search for some text that is deep into the file, less reports

Calculating line numbers... (interrupt to abort)

If I interrupt with Control+C, it also kills produce_output, which stops it from producing further output. Is there any way to send the interrupt to less, so that produce_output keeps running?

I know that I could use kill -INT less_process, but I think there must be a better solution.

Ed McMan
  • 500
  • 1
  • 4
  • 14
  • Related: [Is there any way to exit “less” follow mode without stopping other processes in pipe?](https://unix.stackexchange.com/q/197199/5355) – Piotr Dobrogost Nov 21 '20 at 20:42

4 Answers4

21

Normally all processes in a pipeline run in the same process group, causing all of them to receive the signal. You can use setsid foo | less to run foo in a different pgrp.

u1686_grawity
  • 426,297
  • 64
  • 894
  • 966
  • It light of the problem raised by OP it seems that decision to use CTRL+C as a way to interrupt less is very unfortunate. Do you know why this specific signal was chosen? Would some other signal be less problematic? – Piotr Dobrogost Jan 21 '15 at 11:21
  • @PiotrDobrogost: What other signal would you suggest? There aren't many that have dedicated keyboard shortcuts, only SIGINT (Ctrl-C) and SIGQUIT (Ctrl-\\), and the latter is meant to exit the program immediately, not merely interrupt. The rest are only available via `kill`. – u1686_grawity Jan 21 '15 at 11:28
  • It seems that the problem is caused by using signal to interrupt less. Instead, if it were some *normal* key/shortcut we wouldn't have the problem in the first place. However I guess the need for a signal comes from the fact that process can't use `select` to wait for input both from a file/pipe and terminal at the same time. – Piotr Dobrogost Jan 21 '15 at 12:49
  • @PiotrDobrogost: It can, that's how the `F` (follow) mode works. Pipes and ttys are pollable the same way. – u1686_grawity Jan 21 '15 at 13:10
  • Why do you think that's the way follow mode works? I think the flow of events is that shell gets CTRL+C and sends SIGINT signal to less which gets this signal asynchronously without *listening* to keyboard/terminal. – Piotr Dobrogost Jan 21 '15 at 15:58
  • Note that setsid(1) (setsid(2) syscall as a standalone command) is a Linux-ism. Fortunately, the code is simple, portable to other OSes that have the syscall, and in the public domain, so the command ought to be available at your nearest package manager (either as its own package or as part of a util-linux package; yes, even on non-Linux) – Pierre Lebeaupin Feb 22 '23 at 10:31
10

You can disable line numbers with the

   -n or --line-numbers

option.

produce_output | less -n
Matteo
  • 7,717
  • 2
  • 42
  • 57
  • 1
    -1: may solve OP's instigating problem, but does nothing to answer OP's actual question (i.e., interrupting a process). – goldPseudo May 10 '12 at 00:15
  • 2
    Sorry but starting less with a feature that is not wanted and then try to send a signal to disable a feature you can disable with a switch is a workaround and not a solution. Of course @grawity solution is nice (and I up voted it) but come on: starting the first process in another group to be able to send a signal to interrupt a task (line counting) that is not needed is really a little bit too much work. – Matteo May 10 '12 at 05:26
  • 1
    This is a fair solution to the problem I posed in my question. However, interrupts stop more than just the line counting in less -- for instance, they will interrupt a long search too. So, @grawity's solution is preferred, since it would cover any use of interrupts in less. My bad for not addressing this more clearly in the question! – Ed McMan May 10 '12 at 13:38
  • @EdMcMan Sure I also up voted gravity's solution and I happy to learn something new that can always be useful. – Matteo May 10 '12 at 13:59
2

You can also just do this:

less +F -f <(produce_output)
  • Simple solution and works fine! The `-f` flag is important to read from the temporary pipe created. – Spidey May 21 '20 at 18:03
0

In working with large amounts of output, I've found it very helpful to send the output to a file and use tail -f or less +F to watch, e.g.:

produce_output > out 2>&1 & less +F out

The 2>&1 syntax makes sure that both stdout and stderr go to out---remove that if you only want stdout going to the file. This way, you can inspect the output in various ways (even from a different machine) without having to mess with the program producing the output.

Note that 2>&1 may be bash-specific (I'm not sure). Be sure that you have sufficient disk space for the output file :-)

jrennie
  • 186
  • 1
  • 7
  • Tail will just show you the file, Ed specified that he is using less interactively (e.g., he has to search in the file) – Matteo May 09 '12 at 15:03
  • 1
    `2>&1` is POSIX, bare `>&` is a bashism. – u1686_grawity May 09 '12 at 15:17
  • FWIW, 2>&1 also works on Windows XP, 7, 2008, etc. – jftuga May 09 '12 at 16:05
  • @Matteo: yes, I should have used `less +F` in my example; I just updated my answer. – jrennie May 09 '12 at 22:10
  • `less +F` does not disable line counting, if the file is huge this will take time in any case. And it also has the same problem as originally posted: it does not allow to search on the fly you have to press ctrl+c to tell less to stop following the file (`Waiting for data... (interrupt to abort)`). If you want to search you have to press ctrl+c, search and then re-enable the follow mode. – Matteo May 09 '12 at 22:43
  • 1
    @Matteo: Line counting is not the same issue with `less +F` (since `less +F` processes the data as it is generated). The example I gave does **not** have the same problem as originally posted: ctrl+c will not interrupt `process_output`. If one doesn't care for the 'follow' functionality, one can run `produce_output > out 2>&1`, then `less out`. A problem with `produce_output | less` is that if anything breaks the pipe (e.g. accidentally hitting 'q' from `less`), then `produce_output` will die (without special SIGPIPE handling). – jrennie May 10 '12 at 02:15
  • @jrennie The original problem is that the user had to interrupt the line counting since it was not needed ad was making search slow (the user had to wait). `less +F` will also count lines and according to the manual it will also make several operations slower. Using `less out` as in your last comment will solve the `control-C` problem but why start less with line counting and then interrupt it? You can just start less without line counting and you are done. – Matteo May 10 '12 at 05:22