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
에서 ) 하나를 받으면 시도하기 전에 완료됩니다 .bg
tcsetattr()
그래서 나는 그것을 기능으로 고려해야한다고 생각합니다 ;-)