سؤال

لدي برنامجان (UNIX) A وB يقرأان ويكتبان من stdin/stdout.

مشكلتي الأولى هي كيفية توصيل stdout لـ A بـ stdin لـ B و stdout من B إلى stdin من A.أي شيء مثل | ب ولكن أنبوب ثنائي الاتجاه.أظن أنني أستطيع حل هذا عن طريق باستخدام exec لإعادة التوجيه ولكن لم أستطع الحصول عليه للعمل.البرامج تفاعلية لذا لن يعمل الملف المؤقت.

المشكلة الثانية هي أنني أرغب في تكرار كل اتجاه وتوجيه نسخة مكررة عبر برنامج تسجيل إلى stdout حتى أتمكن من رؤية حركة المرور (المعتمدة على سطر النص) التي تمر بين البرامج.وهنا قد أفلت من العقاب >(...) إذا تمكنت من حل المشكلة الأولى.

يبدو أن هاتين المشكلتين يجب أن يكون لهما حلول معروفة ولكنني لم أتمكن من العثور على أي شيء.

أفضّل حل POSIX Shell، أو على الأقل شيئًا يعمل في bash على cygwin.

بفضل إجاباتك توصلت إلى الحل التالي.تستخدم أوامر A/B nc للاستماع إلى منفذين.يستخدم برنامج التسجيل sed (مع -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

في Shell 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

بالنسبة للجزء الثاني، أعتقد أن المحملة هي الإجابة الصحيحة.فيصبح بالتالي:

# 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)، التي تسمح بذلك.

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.حاليا أنا متمسك بلدي (محاولة في) الحل, ، لكنه يتطلب /dev/fd/0 والتي ربما لا تملكها أيضًا.

على الرغم من أنني لا أحب حقًا جانب تمرير أسطر الأوامر كسلاسل twinpipe (ذكر بواسطة جيبي (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 ...
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top