سؤال

أنا أكتب معالج URI الرسومي لـ GIT: // روابط مع Bash and Zenity ، وأنا أستخدم مربع حوار Zenity 'Text-Info' لإظهار إخراج استنساخ Git أثناء تشغيله ، باستخدام أنابيب FIFO. يبلغ طول البرنامج النصي حوالي 90 سطرًا ، لذلك لن أزعج نفسي بنشره هنا ، ولكن هنا أهم الخطوط:

git clone "$1" "$target" 2>&1 | cat >> /tmp/githandler-fifo &
cat /tmp/githandler-fifo | zenity --text-info --text='Cloning git repository' &

أنا أستخدم FIFO بدلاً من أنبوب مباشر للسماح لهم بالركض بشكل غير متزامن والسماح بقتل Git إذا تم إغلاق نافذة Zenity.

المشكلة هي أن السطر الوحيد الذي يظهر من إخراج Git هو الأول:

Initialized empty Git repository in /home/delan/a/.git/

الخطوط الأخرى مع حساب الكائنات ، وما إلى ذلك لا تظهر أو تظهر على المحطة.

السبب الحالي

يبدو أن الإجماع الحالي على سبب عدم عمله cat غير محظور ويتوقف بعد السطر الأول ، فقط تمرير ذلك إلى zenity وليس الباقي. هدفي هو إجبار الحظر على القراءة ، وإظهار مربع حوار معلومات النص Zenity جميع الإخراج بشكل تدريجي.

git يخرج رسائل التقدم (أي شيء آخر غير رسالة "تهيئة") على STDERR ، ولكن في اللحظة التي أحاول أن أقوم بها إلى ملف إلى ملف أو الاندماج مع stdout ، تختفي الرسائل.

إصلاح المحاولة 1

لقد حاولت كتابة نسختين للحظر من وظائف Cat في C ، والخبز ، والبرايت ، مثل هذا:

#include <stdio.h>
main(int argc, char **argv) {
    int c;
    for (;;) {
        freopen(argv[1], "r", stdin);
        while ((c = getchar()) != EOF)
            putchar(c);
    }
}

#include <stdio.h>
main(int argc, char **argv) {
    int c;
    for (;;) {
        freopen(argv[1], "w", stdout);
        while ((c = getchar()) != EOF)
            putchar(c), fputs("writing", stderr);
    }
}

إنهم يعملون بشكل جيد لأنهم يحظرون ولا يتركون على EOF ، لكنه لم يحل المشكلة بعد. في الوقت الحالي ، يعمل أحدهما ، والآخر ، أو كليهما ، من الناحية النظرية ، ولكن في الممارسة العملية ، لا يظهر Zenity شيئًا على الإطلاق الآن.

إصلاح محاولة 2

اقترح mvds أن استخدام ملف منتظم ، بالاشتراك مع tail -f عوضا عن cat, ، قد تفعل هذا. فوجئت بمثل هذا الحل البسيط (شكرًا!) لقد جربته ، لكن لسوء الحظ ، ظهر السطر الأول فقط في Zenity ولا شيء غير ذلك.

إصلاح المحاولة 3

بعد القيام ببعض الكود المصدر الخاص بـ GIT وتفتيشه ، أدرك أن GIT يخرج جميع معلومات التقدم (أي شيء يتجاوز الرسالة "المهيئة") على STDERR ، وحقيقة أن هذا هو السطر الأول وافتراض أنه بسبب CAT كان الاستقالة في وقت مبكر من EOF افتراضًا مصادفة/مضللة (GIT لا EOF حتى ينتهي البرنامج).

يبدو أن الموقف أصبح أكثر بساطة ، حيث لا ينبغي عليّ تغيير أي شيء من الكود الأصلي (في بداية السؤال) ويجب أن يعمل. في ظروف غامضة ، فإن ناتج STDERR يختفي عند إعادة توجيهه - وهذا شيء يحدث فقط في GIT.

حالة اختبار؟ جرب هذا ، ومعرفة ما إذا كنت ترى أي شيء في الملف (لن تفعل):

git clone git://anongit.freedesktop.org/xorg/proto/dri2proto 2> hurr

هذا يتعارض مع كل ما أعرفه عن Stderr وإعادة التوجيه ؛ لقد كتبت حتى برنامج صغير C يخرج على Stderr و Stdout لإثبات لنفسي أن إعادة التوجيه لا تعمل مع GIT.

إصلاح محاولة 4

تمشيا مع إجابة Jakub Narębski ، بالإضافة إلى ردود على رسائل البريد الإلكتروني التي أرسلتها إلى القائمة البريدية GIT ، --progress هو الخيار الذي أحتاجه. لاحظ أن هذا الخيار يعمل فقط بعد الأمر ، وليس من قبل clone.

النجاح!

شكرا جزيلا لمساعدتك. هذا هو الخط الثابت:

git clone "$1" "$target" --progress > /tmp/githandler-fifo 2>&1 &

هل كانت مفيدة؟

المحلول

أعتقد أن بعض التقارير التقدمية على الأقل يتم إسكاتها عند الإخراج ليس محطة (tty). لست متأكدًا مما إذا كان ذلك ينطبق على حالتك ، ولكن حاول أن تمر --progress خيار "استنساخ git" (أي استخدام git clone --progress <repository>).

على الرغم من أنني لا أعرف ما إذا كان هذا ما تريده.

نصائح أخرى

لسبب واحد ، يتم تحليل التوجيه من اليمين إلى اليسار ، لذلك

git clone "$1" "$target" 2>&1 > /tmp/githandler-fifo &

لا يساوي

git clone "$1" "$target" > /tmp/githandler-fifo 2>&1 &

سيقوم الأخير بإعادة توجيه STDERR إلى stdout ، ثم stdout (بما في ذلك STDERR) إلى الملف. ستعيد التوجيه السابق توجيه stdout إلى الملف ، ثم إظهار Stderr على stdout.

أما بالنسبة للأنابيب إلى zenity (وهو ما لا أعرفه) ، أعتقد أنك قد تصنع الأمور معقدة للغاية مع الأنبوب المسماة. استخدام strace قد تلقي بعض الضوء على الأعمال الداخلية للعمليات التي تطلقها. بالنسبة للأنابيب التي تفتقر إلى الخبرة ، تزيد الأنابيب المسماة الأمور مقارنة بالأنابيب العادية.

بالنظر إلى التجربة مع FIFO المسمى "A" ، أعتقد أن المشكلة تكمن في طريقة معالجة Zenity مدخلاتها. ماذا يحدث إذا كتبت في zenity من لوحة المفاتيح؟ (الشكوك: يتصرف كما تريد ، القراءة إلى EOF.) ومع ذلك ، قد يكون Zenity يعالج إدخال الطرفية (TTY INPUT) باستخدام I/O الحظر العادي ولكنه يستخدم I/O غير المحظور لجميع أنواع الأجهزة الأخرى. I/O غير المحظور جيد للإدخال من الملفات ؛ من المرغوب فيه بالنسبة للمدخلات من الأنابيب أو FIFO ، وما إلى ذلك. إذا استخدمت I/O غير المحظورة ، فإن Zenity ستحصل على السطر الأول من الإخراج ، ثم الخروج من الحلقة التي تفكر في أنه تم ذلك لأن محاولة القراءة الثانية ستشير إلى ذلك لم يكن هناك شيء آخر متاح على الفور.

إن إظهار أن هذا ما يحدث (أو لا) سيكون صعبًا. سأتطلع إلى "الجمالون" أو "Strace" أو شاشة استدعاء النظام الأخرى لتتبع ما تفعله Zenity.

أما بالنسبة إلى الحلول ... إذا كانت الفرضية صحيحة ، فستحتاج إلى إقناع Zenity بأنها تقرأ من محطة وليس FIFO ، لذلك ربما ستحتاج إلى تزوير زائفة (أو pty) ؛ ستكتب العملية الأولى إلى الطرف الرئيسي من Pty وستقوم بترتيب Zenity للقراءة من نهاية العبيد من Pty. قد لا تزال تستخدم FIFO أيضًا - على الرغم من أنها تجعل سلسلة من القيادة طويلة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top