为什么会有`| 的背景工作?less` 被停止,而另一个没有它的正在运行?

Tim*_*Tim 6 bash pipe background-process

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

$ jobs
[3]-  Stopped                 pdfgrep -R -i spark . | less
[4]   Running                 pdfgrep -R -i spark . &
Run Code Online (Sandbox Code Playgroud)
  1. 为什么有一个| less会停止,而另一个没有运行?

    停止的后台作业不会从标准输入读取。所以这不能成为原因。

  2. 我将作业作为后台的原因是我可以在同一个终端会话中做其他事情。

    我使用管道的原因less是因为我不希望输出到 stdout 在我做其他事情时弄乱我的终端会话的屏幕。

    有没有办法实现上述两个目标?我更喜欢不将输出保存到文件而不是将输出保存到文件,因为记住文件、读取和删除它们需要更多时间。

谢谢。

Mar*_*ick 18

让我们更仔细地看看发生了什么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 ---
Run Code Online (Sandbox Code Playgroud)

作业控制限制后台作业中的进程在控制终端上执行某些操作。

  • 如果后台进程试图从终端读取,它将被发送一个SIGTTIN信号,通常会停止(暂停)进程。

  • 如果后台进程试图设置终端的参数,它将被发送一个SIGTTOU信号,这通常也会停止进程。这就是TCSETSW ioctl在这里发生的事情。该less程序会在终端启动后立即尝试将其置于原始模式,甚至在它知道是否有任何内容要显示之前。

    这有一个很好的理由:您不希望后台作业异步更改您的终端,例如,原始模式打开而回声关闭。(后台进程可以使用ioctl获取终端参数TCGETS而无需停止 - 请参阅上面的清单。)

  • 如果后台进程尝试写入终端并且终端tostop设置了标志,则会向其发送SIGTTOU信号。

您可能没有tostop设置标志(运行stty -a检查)。如果你不这样做,这样的后台命令pdfgrep -R -i spark . &不会改变任何终端设置,只要它尝试就可以写入你的终端。

你还写道:

我通过管道减少的原因是因为我不希望输出到 stdout 在我做其他事情时弄乱我的终端会话的屏幕

less 程序最终会将输出发送到终端,一次一屏。如果您运行stty tostopbeforepdfgrep | less &或 before pdfgrep &,那么它们只会在它们处于前台时输出到您的终端。


Eri*_*ers 6

回答您的第二个问题:我使用 screen(1) 通过一个类似 tty 的设备多路复用许多命令。

至少有一个替代方案tmux(1) 和一个用于两者的简化包装器 byobu(1)。


Kus*_*nda 5

less正在尝试与 TTY 交互(输出到),但由于它作为后台作业运行,因此没有可写入的 TTY。pdfgrep另一方面,该实用程序写入标准输出。

在我的系统上,我得到了更具描述性的输出

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

在这个简单的示例中,cat完成发送 my .profileto less,但less无法显示它,因为它是后台作业。因此就有了这条Stopped (tty output) less消息。

但该less过程仍在运行。只是暂时停止了而已。要切换到它,请使用fg %1(该数字对应于“已停止”消息中方括号中报告的作业编号,并且在启动作业时也应该已报告)。


相关:linux 中的 top、top&、top & 命令

  • 谢谢。但我记得后台作业可以在不暂停的情况下输出到标准输出,并且只有在尝试从标准输入读取时才会停止。 (2认同)
  • @Tim 不,`cat` 输出到标准输出。`less` 需要一个控制终端。这是一个互动节目。 (2认同)