x-times에 대한 별도의 프로세스로 manager () 함수를 실행하는 bash 스크립트가 있습니다. 스크립트 내에서 모든 manager () 프로세스로 메시지를 전달하는 방법은 무엇입니까?
익명 파이프에 대해 읽었지만 메시지를 공유하는 방법을 모르겠습니다. 명명 된 파이프를 사용하여 시도했지만 각 프로세스마다 별도의 명명 된 파이프를 만들어야합니까?
가장 우아한 방법은 무엇입니까?
지금까지 내 코드는 다음과 같습니다.
#!/bin/bash
manager () {
while :
do
echo "read what has been passed to \$line"
done
}
x=1
while [ $x -le 5 ]
do
manager x &
x=$(( $x + 1 ))
done
while :
do
while read line
do
echo "What has been passed through the pipe is ${line}"
# should pass $line to every manager process
done < $1
done
exit 0
답변
달성하려는 용어는 멀티플렉싱 입니다.
이것은 bash에서 상당히 쉽게 달성 할 수 있지만 고급 bash 기능이 더 필요합니다.
나는 당신이하려는 일을하는 것으로 생각하는 스크립트를 만들었습니다. 아래에 설명하겠습니다.
#!/bin/bash
manager() {
while IFS= read -r line; do
echo "manager[$1:$BASHPID]: $line"
done
}
fds=()
for (( i=0; i<5; i++ )); do
exec {fd}> >(manager $i)
fds+=( $fd )
done
while IFS= read -r line; do
echo "master: $line"
for fd in "${fds[@]}"; do
printf -- '%s\n' "$line" >&$fd
done
done
manager
STDIN에서 간단히 읽고 식별자와 줄을 STDOUT에 쓰는 bash 함수입니다. 우리는 서브 쉘을 위해 업데이트되지 않는 as $BASHPID
대신에 사용한다 (이것은 우리가 발사하는데 사용할 것이다) .$$
$$
manager
fds
manager
스폰 된 다양한 파일의 STDIN 파이프를 가리키는 파일 디스크립터를 보유하는 배열입니다 .
그런 다음 5 개의 관리자 프로세스를 반복 작성합니다. for (( ))
더 깔끔한 방식으로 구문을 사용합니다 . 이것은 bash에만 해당되지만이 스크립트가 수행하는 몇 가지 작업은 bash마다 다르므로 계속 진행될 수 있습니다.
다음에 우리는 exec {fd}> >(manager $i)
. 이것은 몇 가지 bash 특정 작업을 수행합니다.
첫 번째는입니다 {fd}>
. 그러면 번호 10 또는 그 이후에 사용 가능한 다음 파일 디스크립터를 가져 와서 해당 파일 디스크립터에 지정된 파이프의 쓰기 측이있는 파이프를 열고 파일 디스크립터 번호를 변수에 지정합니다 $fd
.
>(manager $i)
출시 manager $i
기본적으로 대체 >(manager $i)
그 과정의 STDIN에 대한 경로. 따라서 manager
PID 1234로 시작된 경우 (OS에 따라 다름) >(manager $i)
대체 될 수 있습니다 /proc/1234/fd/0
.
따라서 사용 가능한 다음 파일 디스크립터 번호가 10이고 관리자가 PID 1234로 시작 exec {fd}> >(manager $i)
되면 기본적으로 명령 이 exec 10>/proc/1234/fd/0
되고 bash는 이제 해당 관리자의 STDIN을 가리키는 파일 디스크립터를 갖습니다.
bash는 해당 파일 디스크립터 번호를에 넣으므로 이후에 사용하기 위해 $fd
해당 디스크립터를 배열 fds
에 추가 합니다.
나머지는 매우 간단합니다. 마스터는 STDIN에서 라인을 읽고의 모든 파일 디스크립터를 반복 $fds
하여 해당 파일 수신자 ( printf ... >&$fd
) 에게 라인을 보냅니다 .
결과는 다음과 같습니다.
$ /tmp/test.sh
hello
master: hello
manager[0:8876]: hello
manager[1:8877]: hello
manager[4:8880]: hello
manager[2:8878]: hello
manager[3:8879]: hello
world
master: world
manager[0:8876]: world
manager[1:8877]: world
manager[3:8879]: world
manager[2:8878]: world
manager[4:8880]: world
내가 입력 한 곳 hello
과 world
.
답변
tee
그리고 bash
:
cat foo | tee >(manager) >(manager) >(manager) >(manager) >(manager) >/dev/null
관리자 수를 구성 할 수 있거나 다른 관리자의 출력을 혼합하지 않으려는 경우 :
export -f manager
cat foo | parallel --pipe --tee manager ::: {1..10}