여러 프로세스 간 통신


13

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

답변:


25

달성하려는 용어는 멀티플렉싱 입니다.

이것은 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

managerSTDIN에서 간단히 읽고 식별자와 줄을 STDOUT에 쓰는 bash 함수입니다. 우리는 서브 쉘을 위해 업데이트되지 않는 as $BASHPID대신에 사용한다 (이것은 우리가 발사하는데 사용할 것이다) .$$$$manager

fdsmanager스폰 된 다양한 파일의 STDIN 파이프를 가리키는 파일 디스크립터를 보유하는 배열입니다 .
그런 다음 5 개의 관리자 프로세스를 반복 작성합니다. for (( ))더 깔끔한 방식으로 구문을 사용합니다 . 이것은 bash에만 해당되지만이 스크립트가 수행하는 몇 가지 작업은 bash마다 다르므로 계속 진행될 수 있습니다.
 

다음에 우리는 exec {fd}> >(manager $i). 이것은 몇 가지 bash 특정 작업을 수행합니다.
첫 번째는입니다 {fd}>. 그러면 번호 10 또는 그 이후에 사용 가능한 다음 파일 디스크립터를 가져 와서 해당 파일 디스크립터에 지정된 파이프의 쓰기 측이있는 파이프를 열고 파일 디스크립터 번호를 변수에 지정합니다 $fd.

>(manager $i)출시 manager $i기본적으로 대체 >(manager $i)그 과정의 STDIN에 대한 경로. 따라서 managerPID 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

내가 입력 한 곳 helloworld.


(가) 작품이다 @Patrick,하지만 당신은, {FD} 오타를 가지고 있으며 $ {FD}해야한다
c4f4t0r

3
@ c4f4t0r 오타가 아닙니다
Patrick

SUSE 11 @Patrick "bash는 type.bash type.bash : 행 10 : 간부 : {FD} : 찾을 수 없음"내가 $ {FD를} 간부 인 변경과 그런 일
c4f4t0r

2
@ c4f4t0r 오픈 수세 11의 bash 버전은 매우 오래된 버전입니다 (3.2). 이 기능은 bash 4.0에서 구현되었습니다.
Patrick

좋은 정보를 많이 주셔서 감사합니다! nitpick : 당신이 말을 왜 이해할 수 echo -- "$line"또는 printf "%s\n" "$line"-하지만 왜 사용해야합니다 --다음 인수가 하드 코딩 (그리고로 시작하지 않는 경우 -)?
Scott

0

tee그리고 bash:

cat foo | tee >(manager) >(manager) >(manager) >(manager) >(manager) >/dev/null

관리자 수를 구성 할 수 있거나 다른 관리자의 출력을 혼합하지 않으려는 경우 :

export -f manager
cat foo | parallel --pipe --tee manager ::: {1..10}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.