5
$ pdfgrep -R -i spark . | less &
$ pdfgrep -R -i spark . &

$ jobs
[3]-  Stopped                 pdfgrep -R -i spark . | less
[4]   Running                 pdfgrep -R -i spark . &
  1. Why would the one with | less be stopped, while the other one without it is running?

    The stopped backgrounded job doesn't read from stdin. So that can't be the reason.

  2. The reason that I background the jobs is that I can do something else in the same terminal session.

    The reason that I pipe to less is because I don't want the output to stdout messes up the screen of my terminal session when I am doing something else.

    Is there some way to achieve the two goals above? I slightly prefer not saving output to a file over saving output to a file, because it takes a little more to remember the file, read and delete them.

Thanks.

  • less reads from stdin only when I type some commands of less, such as q. Is that what you mean? – Tim Oct 8 '17 at 14:33
  • Why dont you use output redirect if you dont want it in console? – JorgeeFG Oct 9 '17 at 13:31
  • @jorgee How?... – Tim Oct 9 '17 at 13:50
  • using pdfgrep -R -i spark . > /dev/null 2>&1 I don't remember if the & for background goes before the first > or after the 1. I don't have Linux atm. This will send stderr to stdout (terminal by default), but then stdout to /dev/null, discarding it – JorgeeFG Oct 9 '17 at 13:56
  • I need the output – Tim Oct 9 '17 at 14:05
17

Let's look more closely at what's happening to less:

$ pdfgrep -R -i spark . | strace less &
[...]
open("/dev/tty", O_RDONLY|O_LARGEFILE)  = 3
ioctl(3, TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(3, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGTTOU {si_signo=SIGTTOU, si_code=SI_KERNEL} ---
--- stopped by SIGTTOU ---

Job control restricts the processes in a background job from performing certain operations on the controlling terminal.

  • If a background process tries to read from the terminal, it will be sent a SIGTTIN signal, which typically stops (pauses) the process.
  • If a background process tries to set a terminal's parameters, it will be sent a SIGTTOU signal, which also typically stops the process. That's what is happening here with the TCSETSW ioctl. The less program tries to put the terminal into raw mode soon after it starts, even before it knows whether it has anything to display.

    There is a good reason for this: you don't want a background job asynchronously changing your terminal so that, for example, raw mode is on and echo is off. (A background process can get terminal parameters with the TCGETS ioctl without being stopped - see the listing above.)

  • If a background process tries to write to the terminal and the terminal has the tostop flag set, it will be sent the SIGTTOU signal.

You probably don't have the tostop flag set (run stty -a to check). If you don't, a background command like pdfgrep -R -i spark . & that doesn't change any terminal settings will be able to write to your terminal whenever it tries.

You also wrote:

The reason that I pipe to less is because I don't want the output to stdout messes up the screen of my terminal session when I am doing something else

The less program is ultimately going to send output to the terminal, one screenful at a time. If you run stty tostop before pdfgrep | less &, or before pdfgrep &, then they will only output to your terminal when they are in the foreground.

6

To answer your second question: I use screen(1) to multiplex many commands through one tty-like device.

There is at least one alternative, tmux(1) and a simplifying wrapper for both, byobu(1).

5

less is trying to interact with (output to) the TTY, but since it's running as a background job, it has no TTY to write to. The pdfgrep utility, on the other hand, writes to standard output.

On my system, I get the slightly more descriptive output

$ cat ~/.profile | less &
[1] 51758 67354
$
[1] + Done                 cat ~/.profile |
      Stopped (tty output) less

In this simple example, cat finishes sending my .profile to less, but less is unable to display it since it's a background job. Hence the Stopped (tty output) less message.

The less process is still running though. It's only temporarilly stopped. To switch to it, use fg %1 (the number corresponds to the job number reported in square brackets in the "stopped" message, and it should also have been reported when you started the job).


Related: top, top&, top & commands in linux

  • 2
    Thanks. But I remember a background job can output to stdout without being paused, and it is stopped only when trying to read from stdin. – Tim Oct 8 '17 at 14:35
  • cat ~/.profile also outputs to tty too, but cat ~/.profile & won't stop it. – Tim Oct 8 '17 at 14:38
  • 1
    @Tim What makes you think less sends its output to its standard output? – Kusalananda Oct 8 '17 at 14:38
  • 2
    @Tim No, cat outputs to standard output. less needs a controlling terminal. It's an interactive program. – Kusalananda Oct 8 '17 at 14:39
  • Thanks. Is there any way for my question in part 2? – Tim Oct 8 '17 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.