나는 Manager() 함수를 별도의 프로세스로 x번 실행하는 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
답변1
당신이 성취하고 싶은 것을 가리키는 용어는 다음과 같습니다.재사용.
이는 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 함수입니다. $BASHPID
대신 서브셸을 업데이트하지 않기 $$
때문에 사용합니다 $$
(이는 manager
.
fds
manager
s에 의해 생성된 다양한 STDIN 파이프를 가리키는 파일 설명자를 보유하는 배열입니다.
그런 다음 5개의 관리자 프로세스를 반복하고 생성합니다. 나는 for (( ))
여러분이 사용하는 방식 대신 구문을 사용하고 있습니다. 왜냐하면 그것이 더 깔끔하기 때문입니다. 이는 bash에만 해당되지만 스크립트가 수행하는 작업 중 일부는 bash에만 해당되므로 끝까지 진행하는 것이 좋습니다.
다음으로 우리는 도착했습니다 exec {fd}> >(manager $i)
. 이는 더 많은 bash 관련 작업을 수행합니다.
그 중 첫 번째는 입니다 {fd}>
. 이는 번호가 10 이상인 사용 가능한 다음 파일 설명자를 가져오고, 파이프를 열고, 파이프의 쓰기 끝을 해당 파일 설명자에 할당하고, 파일 설명자 번호를 변수에 할당합니다 $fd
.
프로세스의 STDIN 경로를 시작 >(manager $i)
하고 manager $i
기본적으로 교체합니다 . >(manager $i)
따라서 manager
PID 1234로 부팅할 경우 (운영체제에 따라) >(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
?
답변2
tee
그리고 bash
:
cat foo | tee >(manager) >(manager) >(manager) >(manager) >(manager) >/dev/null
관리자 수를 구성할 수 있어야 하거나 여러 관리자의 출력이 혼합되지 않도록 하려는 경우:
export -f manager
cat foo | parallel --pipe --tee manager ::: {1..10}