`| less`を含むバックグラウンドジョブが停止されていない他のジョブが実行されるのはなぜですか?

`| less`を含むバックグラウンドジョブが停止されていない他のジョブが実行されるのはなぜですか?
$ pdfgrep -R -i spark . | less &
$ pdfgrep -R -i spark . &

$ jobs
[3]-  Stopped                 pdfgrep -R -i spark . | less
[4]   Running                 pdfgrep -R -i spark . &
  1. なぜそれを持っているのは| less止まり、そうでないものは実行されていますか?

    停止したバックグラウンドジョブは標準入力から読み取られません。したがって、それは理由になることはできません。

  2. タスクをバックグラウンドに設定したのは、同じ端末セッションで別のタスクを実行できるためです。

    私がパイプを使用する理由lessは、他のことをしている間にstdoutへの出力がターミナルセッションの画面を乱すことを望まないからです。

    上記の2つの目標を達成する方法はありますか?ファイルの記憶、読み取り、削除には時間がかかるため、出力をファイルに保存するよりも出力をファイルに保存しない方が少し良いです。

ありがとうございます。

答え1

何が起こっているのかを詳しく見てみましょう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 ---

タスク制御は、バックグラウンドタスクのプロセスが制御端末で特定のタスクを実行することを制限する。

  • バックグラウンドプロセスが端末からデータを読み取ろうとすると、通常、SIGTTINプロセスを停止(一時停止)する信号が送信されます。

  • バックグラウンドプロセスが端末のパラメータを設定しようとすると、信号はそのプロセスにSIGTTOU送信され、通常プロセスも停止します。それがここで起こったことです。TCSETSW I/W制御。プログラムlessは、開始直後に、表示する項目があるかどうかを知る前に端末を生モードに切り替えようとします。

    これには妥当な理由があります。つまり、ネイティブモードがオンでエコーがオフになっているかのように、バックグラウンドジョブが端末を非同期的に変更したくありません。 (バックグラウンドプロセスは得る停止せずにioctlの端末引数を使用してくださいTCGETS。上記のリストを参照してください。 )

  • バックグラウンドプロセスが端末に書き込みを試み、端末にフラグが設定されている場合、tostop信号は端末に送信されますSIGTTOU

tostopフラグが設定されていない可能性があります(実行しstty -aて確認)。そうしないと、これらのバックグラウンドコマンドはpdfgrep -R -i spark . &端末設定を変更せず、試みると端末に書き込むことができます。

また、次のように書きました。

私がlessを使う理由は、他のことをしている間にstdoutに出力してターミナルセッション画面を乱すことを望まないからです。

lessプログラムは最終的に一度に1画面ずつ出力を端末に送信します。stty tostopbeforepdfgrep | less &またはbeforeを実行すると、pdfgrep &フォアグラウンドにある場合にのみ端末に出力されます。

答え2

2番目の質問に答えるには:ttyなどのデバイスを介して多くのコマンドを多重化するためにscreen(1)を使用します。

少なくとも一つ選ぶ、tmux(1)、byobu(1)(両方の単純化されたラッパー)。

答え3

lessTTYと対話(出力)しようとしていますが、バックグラウンドジョブとして実行されているため、書き込むTTYはありません。pdfgrep一方、このユーティリティは標準出力に書き込みます。

私のシステムでは、より説明的な出力を取得します。

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

この簡単な例では、cat完了はmy.profileをに送信しますが、バックlessグラウンドlessジョブであるため表示できません。したがって、このStopped (tty output) lessメッセージが表示されます。

ただし、lessプロセスはまだ実行中です。これだけ一時的に停止しました。これを切り替えるには、次のようにしますfg %1(この数字は「中止」メッセージで角かっこ内に報告されたジョブ番号に対応し、ジョブの開始時にも報告する必要があります)。


関連:Linuxのtop、top&、top&コマンド

関連情報