एक segfaulting कार्यक्रम से पाइपिंग उत्पादन


13

मेरे पास एक स्क्रिप्ट है जो एक प्रोग्राम (विशेष रूप से, ttf2afmटेटेक्स 3.0 का हिस्सा) को कॉल करती है जो कभी-कभी सेगुलेट्स और कभी-कभी नहीं होती है। मुझे जो जानकारी चाहिए वह हमेशा सेग्यूफ़ेट्स से पहले ही प्रिंट हो जाती है , लेकिन मुझे एक कठिन समय मिल रहा है कि पाइप के पुनर्निर्देशन को विफल होने से रोका जाए और जब प्रोग्राम विफल हो जाए तो पाइप को कुछ भी आउटपुट न करें।

मैंने एक फीफो के माध्यम से पुनर्निर्देशन की कोशिश की है, इस प्रक्रिया trueको अंत में समतल करना, एक शेल फ़ंक्शन से निष्पादित करना और इनकैश करना sh -c, लेकिन स्क्रिप्ट कभी भी प्रक्रिया को कुछ भी करने नहीं देती है, पुनर्निर्देशित या अन्यथा- strr को भी नहीं।

मुझे पता है कि यह आउटपुट में सक्षम है, क्योंकि यह पूरी तरह से कमांड-लाइन से देने में सक्षम है, लेकिन किसी कारण से स्क्रिप्ट से नहीं।

मेरा प्रश्न यह है कि क्या स्क्रिप्ट के लिए इस तथ्य को अनदेखा करना है कि कार्यक्रम में कोई कमी है और मुझे वैसे भी आउटपुट दें?

मैं BASH 4.1.10 (2) -release चला रहा हूं।

जवाबों:


12

प्रोग्राम आमतौर पर दक्षता के लिए अपने आउटपुट को बफर करते हैं। यही है, वे एक मेमोरी क्षेत्र (जिसे बफर कहा जाता है) में आउटपुट जमा करते हैं, और वे वास्तव में आउटपुट तभी निकालते हैं जब बफर पूर्ण होता है या प्रोग्राम में कुछ प्रमुख बिंदुओं पर होता है। जब प्रोग्राम सामान्य रूप से समाप्त होता है, तो यह आउटपुट बफर को फ्लश करता है (यानी इसमें कोई भी डेटा प्रिंट करता है)। जब यह अलग हो जाता है, बफर की सामग्री खो जाती है।

प्रोग्राम को सीधे टर्मिनल में चलाते समय आप इस आशय का अवलोकन नहीं करते हैं क्योंकि प्रोग्राम के आउटपुट टर्मिनल से जुड़े होने पर व्यवहार भिन्न होता है (जैसा कि एक नियमित फ़ाइल या पाइप के विपरीत)। एक टर्मिनल में, डिफ़ॉल्ट व्यवहार प्रत्येक पंक्ति के अंत में बफर को फ्लश करना है। इसलिए आप प्रत्येक पूर्ण पंक्ति देखेंगे जो उस बिंदु तक उत्पन्न होती है जब प्रोग्राम सेफ़ल्ट्स।

आप प्रोग्राम को टर्मिनल में चलाने और उसके आउटपुट को इकट्ठा करने के लिए मजबूर कर सकते हैं। सबसे सरल तरीका है दौड़ना script। ऐसी कई झुंझलाहट हैं जिनके लिए आपको काम करना होगा:

  • script ट्रांसक्रिप्ट फ़ाइल में एक हेडर लाइन जोड़ता है, जिसे आपको बाद में निकालना होगा।
  • script यदि आप सीगफॉल्ट या किसी अन्य त्रुटि के बारे में जानना चाहते हैं, तो कमांड की स्थिति कोड वापस नहीं करता है, इसलिए आपको इसे कहीं और सहेजना होगा।
  • scriptसामान्य उत्पादन और त्रुटि का कारण होगा; आप बेहतर आउटपुट को अलग फ़ाइल में सहेजेंगे।
export FONT="foo"
script -q -c '
    ttf2afm "$FONT.ttf" 2>"$FONT.ttf2afm-err";
    echo $? >"$FONT.ttf2afm-status"
' "$FONT.ttf2afm-typescript"
tail -n +2 <"$FONT.ttf2afm-typescript" >"foo.afm"
rm "$FONT.ttf2afm-typescript"
if [ "$(cat "$FONT.ttf2afm-status")" -ne 0 ]; then
  echo 1>&2 "Warning: ttf2afm failed"
  cat "$FONT.ttf2afm-err"
fi

कुछ शेल सेटिंग की तरह अधिक सुरुचिपूर्ण समाधान नहीं है, जो आउटपुट बफर को 0 या कुछ और सेट करेगा?
amphetamachine

4

मैंने अंततः परीक्षण और त्रुटि की एक प्रक्रिया के माध्यम से इसका पता लगाया। समाधान तरह का है:

(trap 'true' ERR; exec ttf2afm "$FONT") |
grep ...

जाहिरा तौर पर फंसे हुए त्रुटि के साथ उपधारा प्रक्रिया को लेने का execकारण बनता ttf2afmहै, जिससे यह एक ऐसे वातावरण में संचालित होता है जहां यह अलग नहीं होता है।

ऑल-इनक्लूसिव ERRसिग्नल को ट्रैप करने से सबस्क्रिप्शन को मरने से रोक दिया जाएगा और मुख्य स्क्रिप्ट को सिग्नल भेज दिया जाएगा - जो प्रोग्राम के फेल होने पर तुरंत समाप्त हो जाएगा।

एक ही समस्या यह है कि कर्नेल स्वयं स्टैक ट्रेस कचरा के पूरे गुच्छा को कंसोल डिवाइस से सीधे आउटपुट करेगा, एक बार प्रक्रिया सेगफॉल्ट होने के बाद, इसलिए इसे आउटपुट होने से रोकने का कोई तरीका नहीं है [कि मुझे पता है], लेकिन इससे कोई फर्क नहीं पड़ता क्योंकि यह stdout या stderr को प्रभावित नहीं करता है।


3
यदि आप के लिए यह काम करता है, लेकिन मैं पूरे विश्वास के साथ दावा कर सकते हैं कि कारण यह काम करता है मुझे खुशी है नहीं क्योंकि बैश 0. बैश के लिए उत्पादन बफर आकार द्वारा प्रयोग किया जाता बफरिंग प्रभावित नहीं कर सकते स्थापित कर रही है ttf2afmसीधे। मुझे आश्चर्य है कि कैसे (trap true ERR; exec ttf2afm "$FONT")| …अलग व्यवहार करता है ttf2afm "$FONT" | …
गिल्स एसओ- बुराई को रोकना '
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.