
pv
各パイプラインで一連のコマンドパイプラインを実行したいと思います。例は次のとおりです。
for p in 1 2 3
do
cat /dev/zero | pv -N $p | dd of=/dev/null &
done
パイプラインの実際のコマンドは重要ではありません(cat
/dd
は単なる例です)...
目標は同時に実行される4つのパイプラインで、それぞれ独自のpv
出力があります。ただし、バックグラウンドでこのようなコマンドを入力しようとすると、pv
コマンドは停止し、4つの停止したジョブのみが表示されます。私はそれを試しましたが、{...|pv|...}&
同じbash -c "...|pv|..." &
結果を得ました。
pv
複数のコマンドパイプラインを同時に実行するには?
答え1
xargs
次のオプションを使用して-P
これを実行できることがわかりました。
josh@subdivisions:/# seq 1 10 | xargs -P 4 -I {} bash -c "dd if=/dev/zero bs=1024 count=10000000 | pv -c -N {} | dd of=/dev/null"
3: 7.35GiB 0:00:29 [ 280MiB/s] [ <=> ]
1: 7.88GiB 0:00:29 [ 312MiB/s] [ <=> ]
4: 7.83GiB 0:00:29 [ 258MiB/s] [ <=> ]
2: 6.55GiB 0:00:29 [ 238MiB/s] [ <=> ]
繰り返す配列の出力を次に送信しますxargs
。すべてのコマンドを同時に実行するには、次のようにします。-P 0
答え2
pv
バックグラウンドで起動できません。
src/main/main.c
ソースコードファイルに示すように、pv
端末(構造体)にフラグを設定します。これは、フォアグラウンドにないときに端末に書き込もうとしたときにそれを受信し、信号ハンドラでキャプチャしてから端末を「混乱させない」ように出力をリダイレクトするためです。TOSTOP
tcsetattr()
c.c_lflag
termios
SIGTTOU
/dev/null
/* * Set terminal option TOSTOP so we get signal SIGTTOU if we try to * write to the terminal while backgrounded. * * Also, save the current terminal attributes for later restoration. */ memset(&t, 0, sizeof(t)); tcgetattr(STDERR_FILENO, &t); t_save = t; t.c_lflag |= TOSTOP; tcsetattr(STDERR_FILENO, TCSANOW, &t);
もちろんこれは嫌なことです。それ自体にフラグを設定するのではなく、端末を使用するすべてのプログラムに対して設定するからです。
しかし、それはすべてではありません。 glibcで説明したように手動:
関数: int tcsetattr(int filedes, int when, const struct termios *termios-p)
この関数が制御端末のバックグラウンド・プロセスから呼び出されると、通常、プロセスが端末に書き込もうとするように、SIGTTOU信号がプロセス・グループ内のすべてのプロセスに送信されます。例外は、呼び出しプロセス自体が SIGTTOU シグナルを無視またはブロックする場合です。この場合、操作は実行されますが、信号は送信されません。ジョブ制御を参照してください。
それらはブロックまたは無視せず、SIGTTOU
確認もしませんtcsetattr()
(-1を返し、errno
次に設定されます)。EINTR
もし以前はすでにシグナルハンドラを設定していますSIGTTOU
。
したがって、プロセスが停止します。 (コマンドSIGCONT
から)1つを受け取ると、試す前に完了します。bg
tcsetattr()
だから私はそれを機能として考慮する必要があると思います;-)