입력 연결 _and_output Shell/bash에서 두 명령 사이의 연결
문제
나는 Stdin/stdout에서 읽고 쓰는 두 가지 (UNIX) 프로그램 A와 B가 있습니다.
첫 번째 문제는 A의 Stdout을 B의 Stdin에 연결하는 방법입니다. 그리고 aie의 stdin에 b의 stdout, a | b 그러나 양방향 파이프. 나는 이것을 해결할 수 있다고 생각한다 exec을 사용하여 리디렉션 그러나 나는 그것을 일할 수 없었다. 프로그램은 대화식이므로 임시 파일이 작동하지 않습니다.
두 번째 문제는 각 방향을 복제하고 로깅 프로그램을 통해 STDOUT를 통해 중복을 파이프하여 프로그램간에 전달되는 (텍스트 라인 기반) 트래픽을 볼 수 있다는 것입니다. 여기서 첫 번째 문제를 해결할 수 있다면 티> (...)로 도망 갈 수 있습니다.
이 두 가지 문제는 잘 알려진 솔루션을 가져야하는 것처럼 보이지만 아무것도 찾을 수 없습니다.
나는 posix 쉘 솔루션 또는 적어도 Cygwin에서 Bash에서 작동하는 것을 선호합니다.
귀하의 답변 덕분에 다음 솔루션을 생각해 냈습니다. A/B 명령은 NC를 사용하여 두 개의 포트를 듣습니다. 로깅 프로그램은 SED를 사용합니다 (Unfufered Processing의 경우 -U와 함께).
bash-3.2$ fifodir=$(mktemp -d)
bash-3.2$ mkfifo "$fifodir/echoAtoB"
bash-3.2$ mkfifo "$fifodir/echoBtoA"
bash-3.2$ sed -u 's/^/A->B: /' "$fifodir/echoAtoB" &
bash-3.2$ sed -u 's/^/B->A: /' "$fifodir/echoBtoA" &
bash-3.2$ mkfifo "$fifodir/loopback"
bash-3.2$ nc -l -p 47002 < "$fifodir/loopback" \
| tee "$fifodir/echoAtoB" \
| nc -l -p 47001 \
| tee "$fifodir/echoBtoA" > "$fifodir/loopback"
이는 포트 47001 및 47002에 연결하고 모든 트래픽을 표준 출력으로 반향합니다.
쉘 2에서 :
bash-3.2$ nc localhost 47001
쉘 3에서 :
bash-3.2$ nc localhost 47002
이제 쉘 2에 입력 된 라인은 쉘 3에 기록되며 그 반대도 마찬가지이며 트래픽은 다음과 같은 것과 같은 쉘 1에 로그온했습니다.
B->A: input to port 47001
A->B: input to port 47002
상기는 Cygwin에서 테스트되었습니다
업데이트 : 위의 스크립트는 며칠 후 작동 중지되었습니다 (!). 분명히 교착 상태가 될 수 있습니다. 답의 일부 제안 중 일부는 더 신뢰할 수 있습니다.
다른 팁
명명 된 파이프는 어떻습니까?
# mkfifo foo
# A < foo | B > foo
# rm foo
두 번째 부분의 경우 Tee가 정답이라고 생각합니다. 그래서 그것은 다음과 같습니다.
# A < foo | tee logfile | B > foo
당신은 아마도 이름이 지정된 파이프로 도망 갈 수 있습니다.
mkfifo pipe
gawk '$1' < pipe | gawk '$1' > pipe
당신이 사용할 수있는 예상하다.
기대는 Telnet, FTP, Passwd, FSCK, Rlogin, Tip 등과 같은 대화식 응용 프로그램을 자동화하는 도구입니다.
다음 코드를 사용할 수 있습니다 ( 기대를 탐구합니다 Book) 시작점 - Proc1의 출력을 Proc2의 입력에 연결하고 요청한대로 그 반대도 마찬가지입니다.
#!/usr/bin/expect -f
spawn proc1
set proc1 $spawn_id
spawn proc2
interact -u $proc1
나는 이것에 많은 시간을 보냈고, 포기했고, 마지막으로 KSH (Korn Shell)를 사용하기로 결정했습니다.
cmd1 |& cmd2 >&p <&p
어디 |&
공동 프로세스를 시작하는 (파이프) 연산자입니다. &p
해당 공동 프로세스의 파일 디스크립터입니다.
나는 한 시점 에서이 문제를 겪었고이 간단한 C 프로그램을 함께 던졌습니다.
#include <stdio.h>
#include <unistd.h>
#define PERROR_AND_DIE(_x_) {perror(_x_); _exit(1);}
int main(int argc, char **argv) {
int fd0[2];
int fd1[2];
if ( argc != 3 ) {
fprintf(stdout, "Usage %s: \"[command 1]\" \"[command 2]\"\n", argv[0]);
_exit(1);
}
if ( pipe(fd0) || pipe(fd1) ) PERROR_AND_DIE("pipe")
pid_t id = fork();
if ( id == -1 ) PERROR_AND_DIE("fork");
if ( id ) {
if ( -1 == close(0) ) PERROR_AND_DIE("P1: close 0");
if ( -1 == dup2(fd0[0], 0) ) PERROR_AND_DIE("P1: dup 0"); //Read my STDIN from this pipe
if ( -1 == close(1) ) PERROR_AND_DIE("P1: close 1");
if ( -1 == dup2(fd1[1], 1) ) PERROR_AND_DIE("P1: dup 1"); //Write my STDOUT here
execl("/bin/sh", "/bin/sh", "-c", argv[1], NULL);
PERROR_AND_DIE("P1: exec")
}
if ( -1 == close(0) ) PERROR_AND_DIE("P2: close 0");
if ( -1 == dup2(fd1[0], 0) ) PERROR_AND_DIE("P2: dup 0");
if ( -1 == close(1) ) PERROR_AND_DIE("P2: close 1");
if ( -1 == dup2(fd0[1], 1) ) PERROR_AND_DIE("P2: dup 1");
execl("/bin/sh", "/bin/sh", "-c", argv[2], NULL);
PERROR_AND_DIE("P2: exec")
}
이 질문은 비슷합니다 하나 나는 전에 물었다. 다른 사람들이 제안한 솔루션은 이름이 지정된 파이프를 사용하는 것이었지만 Cygwin에는 파이프가 없다고 생각합니다. 현재 나는 고집하고있다 내 자신의 (a) 솔루션, 그러나 필요합니다 /dev/fd/0
아마 당신도 가지고 있지 않을 것입니다.
나는 통과 명령 라인-스트링스 측면을 정말로 좋아하지 않지만 twinpipe
(Jeebee가 언급했습니다.139495)), Cygwin에서 유일한 옵션 일 수 있습니다.
"Coproc"을 제안합니다 :
#! /bin/bash
# initiator needs argument
if [ $# -gt 0 ]; then
a=$1
echo "Question $a"
else
read a
fi
if [ $# -gt 0 ]; then
read a
echo "$a" >&2
else
echo "Answer to $a is ..."
fi
exit 0
그런 다음이 세션을 참조하십시오.
$ coproc ./dialog
$ ./dialog test < /dev/fd/${COPROC[0]} > /dev/fd/${COPROC[1]}
Answer to Question test is ...