ऑर्डर किए गए STDOUT / STDERR को कैसे कैप्चर करें और टाइमस्टैम्प / उपसर्ग जोड़ें?


25

मैंने लगभग सभी उपलब्ध समान सवालों का पता लगाया है , कोई फायदा नहीं हुआ।

मुझे समस्या के बारे में विस्तार से बताएं:

मैं कुछ अप्राप्य स्क्रिप्ट्स चलाता हूं और ये मानक आउटपुट और मानक त्रुटि रेखाएं उत्पन्न कर सकते हैं, मैं उन्हें अपने सटीक क्रम में कैप्चर करना चाहता हूं जैसा कि एक टर्मिनल एमुलेटर द्वारा प्रदर्शित किया गया है और फिर "STDERR:" और "STDOUT:" जैसे उपसर्ग जोड़ते हैं।

मैंने पाइप और यहां तक ​​कि उन पर एपोल-आधारित दृष्टिकोण का उपयोग करने की कोशिश की है, कोई फायदा नहीं हुआ। मुझे लगता है कि समाधान पीट उपयोग में है, हालांकि मैं उस पर कोई मास्टर नहीं हूं। मैंने ग्नोम के वीटीई के स्रोत कोड में भी देखा है , लेकिन यह बहुत अधिक उत्पादक नहीं है।

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

क्या कोई ऐसा ही कुछ कर पाया है? या यह असंभव है? मुझे लगता है कि अगर एक टर्मिनल एमुलेटर यह कर सकता है, तो यह नहीं है - शायद एक छोटा सी प्रोग्राम बनाकर PTY (एस) को अलग तरीके से हैंडल किया जाए?

आदर्श रूप से मैं इन 2 धाराओं (STDOUT और STDERR) को पढ़ने के लिए अतुल्यकालिक इनपुट का उपयोग करूंगा और फिर उन्हें मेरी दूसरी जरूरतों को फिर से प्रिंट करूंगा, लेकिन इनपुट का क्रम महत्वपूर्ण है!

नोट: मैं stderred के बारे में पता है, लेकिन यह मेरे लिए बैश लिपियों के साथ काम नहीं करता है और आसानी से एक उपसर्ग जोड़ने के लिए संपादित नहीं किया जा सकता है (क्योंकि यह मूल रूप से syscalls के बहुत लपेटता है)।

अद्यतन: दो gists के नीचे जोड़ा गया

(उप-सेकंड रैंडम देरी नमूना स्क्रिप्ट में जोड़ा जा सकता है जो मैंने एक सुसंगत परिणाम साबित करने के लिए प्रदान किया है)

अद्यतन: इस प्रश्न का समाधान भी इस अन्य प्रश्न को हल करेगा , जैसा कि @Gilles ने बताया। हालांकि मैं इस नतीजे पर पहुंचा हूं कि यहां और वहां जो पूछा गया है वह करना संभव नहीं है2>&1दोनों धाराओं का उपयोग करते समय सही ढंग से पीटीआई / पाइप स्तर पर विलय कर दिया जाता है, लेकिन धाराओं को अलग-अलग और सही क्रम में उपयोग करने के लिए वास्तव में स्ट्रीड के दृष्टिकोण का उपयोग करना चाहिए जो कि सीस्कॉल हुकिंग को आमंत्रित करता है और कई मायनों में गंदे के रूप में देखा जा सकता है।

मैं इस प्रश्न को अद्यतन करने के लिए उत्सुक रहूंगा यदि कोई व्यक्ति उपरोक्त को बाधित कर सकता है।


1
क्या यह वह नहीं है जो आप चाहते हैं? stackoverflow.com/questions/21564/…
slm

@ एसएलएम शायद नहीं, क्योंकि ओपी को अलग-अलग तारों को अलग-अलग धाराओं के लिए तैयार करने की आवश्यकता है ।
पीटर सेफ़

क्या आप साझा कर सकते हैं कि आदेश इतना महत्वपूर्ण क्यों है? हो सकता है कि आपकी समस्या के आसपास कोई और तरीका हो ...
याचिकाकर्ता

@peterph यह एक शर्त है, अगर मेरे पास लगातार आउटपुट नहीं हो सकता है तो मैं इसे पढ़ने के बजाय / dev / null को भेजूंगा और इसके द्वारा भ्रमित हो सकता हूं :) 2> और 1 उदाहरण के लिए ऑर्डर सुरक्षित रखता है, लेकिन इस तरह की अनुमति नहीं देता है अनुकूलन के बारे में जो मैं इस सवाल में पूछता हूं
Deim0s

जवाबों:


12

आप सहसंसाधनों का उपयोग कर सकते हैं। सरल आवरण जो किसी दिए गए कमांड के दोनों आउटपुट को दो sedइंस्टेंस (एक stderrदूसरे के लिए stdout) के लिए फीड करता है , जो टैगिंग करते हैं।

#!/bin/bash
exec 3>&1
coproc SEDo ( sed "s/^/STDOUT: /" >&3 )
exec 4>&2-
coproc SEDe ( sed "s/^/STDERR: /" >&4 )
eval $@ 2>&${SEDe[1]} 1>&${SEDo[1]}
eval exec "${SEDo[1]}>&-"
eval exec "${SEDe[1]}>&-"

कई बातों पर ध्यान दें:

  1. यह कई लोगों के लिए (मेरे सहित) के लिए एक जादू भस्म है - एक कारण के लिए (नीचे दिए गए लिंक देखें)।

  2. इसकी कोई गारंटी नहीं है कि यह कभी-कभार कुछ लाइनों की अदला-बदली नहीं करेगा - यह सब कॉपोरोसेस के शेड्यूलिंग पर निर्भर करता है। दरअसल, यह लगभग गारंटी है कि किसी समय में यह होगा। उस ने कहा, यदि आदेश को सख्ती से एक समान रखते हुए, आपको डेटा को दोनों से stderrऔर stdinएक ही प्रक्रिया में संसाधित करना होगा, अन्यथा कर्नेल शेड्यूलर (और इच्छाशक्ति) इसे गड़बड़ कर सकता है।

    अगर मैं समस्या को सही ढंग से समझता हूं, तो इसका मतलब है कि आपको शेल को एक प्रक्रिया (जो AFAIK किया जा सकता है) में दोनों धाराओं को पुनर्निर्देशित करने की आवश्यकता होगी। परेशानी तब शुरू होती है जब यह प्रक्रिया पहले ही तय करने लगती है कि उसे क्या करना है - यह दोनों डेटा स्रोतों को प्रदूषित करना होगा और कुछ बिंदु पर राज्य में पहुंच जाएगा जहां यह एक धारा को संसाधित करेगा और डेटा खत्म होने से पहले दोनों धाराओं तक पहुंच जाएगा। और ठीक यही वह जगह है जहां यह टूट जाता है। इसका मतलब यह भी है, कि आउटपुट syscalls को लपेटना stderredसंभवतया आपके वांछित परिणाम को प्राप्त करने का एकमात्र तरीका है (और तब भी आपको एक समस्या हो सकती है, जब एक मल्टीप्रोसेसर सिस्टम पर कुछ मल्टीथ्रेड हो जाता है)।

जहां तक कॉप्रोसेस को स्टीफन के उत्कृष्ट उत्तर को पढ़ने के लिए सुनिश्चित करें कि आप बैश में कमांड कोप्रोक का उपयोग कैसे करते हैं? गहराई से जानकारी के लिए।


आपके उत्तर के लिए धन्यवाद @peterph, हालांकि मैं विशेष रूप से आदेश को संरक्षित करने के तरीकों की तलाश कर रहा हूं। नोट: मुझे लगता है कि आपके इंटरप्रिटर को आपके ./test1.sh: 3: ./test1.sh: Syntax error: "(" unexpectedद्वारा उपयोग की जाने वाली प्रक्रिया के प्रतिस्थापन के कारण बैश किया जाना चाहिए (मुझे आपकी स्क्रिप्ट कॉपी / पेस्ट करके मिलती है)
Deim0s

बहुत संभावना है तो, मैं इसे में भाग गया bashके साथ /bin/sh(यकीन नहीं क्यों मैं इसे वहाँ था)।
पीटर

मैंने सवाल को थोड़ा अपडेट किया है, जहां स्ट्रीम मिक्स-अप हो सकता है।
पीटर सेफ़

1
eval $@काफी छोटी गाड़ी है। "$@"यदि आप एक सटीक कमांड लाइन के रूप में अपनी दलीलें चलाना चाहते हैं, तो उपयोग करें - evalहार्ड-टू-प्रेडिक्ट (और संभावित रूप से दुर्भावनापूर्ण, यदि आप फ़ाइल नाम या अन्य सामग्री पास कर रहे हैं जिसे आप नियंत्रित नहीं करते हैं, तो व्याख्या की एक परत फेंकता है। तर्क) व्यवहार, और यहां तक ​​कि मोरसो को उद्धृत करने में असफल होना (कई शब्दों में रिक्त स्थान के साथ नामों को विभाजित करता है, ग्लब्स का विस्तार करता है, भले ही उन्हें पहले शाब्दिक रूप से उद्धृत किया गया हो)।
चार्ल्स डफी

1
इसके अलावा, आधुनिक-से-टू-है-कोप्रोसेस बश में, आपको एक चर में नामित फ़ाइल विवरणकों को बंद करने की आवश्यकता नहीं हैevalexec {SEDo[1]}>&-के रूप में काम करेंगे (हाँ, $पहले एक {जानबूझकर की कमी थी)।
चार्ल्स डफी

5

विधि # 1। फ़ाइल डिस्क्रिप्टर और awk का उपयोग करना

इस SO Q & A शीर्षक से समाधान का उपयोग करने के बारे में कुछ ऐसा है: क्या पाठ की पंक्तियों के लिए टाइमस्टैम्प को प्रीपेन्ड करने के लिए यूनिक्स उपयोगिता है? और यह SO Q & A शीर्षक: शेल स्क्रिप्ट में दो अलग-अलग प्रक्रियाओं में पाइप STDOUT और STDERR?

पहुंच

चरण 1, हम बैश में 2 कार्य बनाते हैं, जो टाइमस्टैम्प संदेश को कॉल करेगा:

$ msgOut () {  awk '{ print strftime("STDOUT: %Y-%m-%d %H:%M:%S"), $0; fflush(); }'; }
$ msgErr () {  awk '{ print strftime("STDERR: %Y-%m-%d %H:%M:%S"), $0; fflush(); }'; }

चरण 2 आप इच्छित संदेश प्राप्त करने के लिए उपरोक्त कार्यों का उपयोग करेंगे:

$ { { { ...command/script... } 2>&3; } 2>&3 | msgErr; } 3>&1 1>&2 | msgOut

उदाहरण

यहाँ मैंने एक उदाहरण दिया है जो aSTDOUT को लिखेगा , 10 सेकंड के लिए सोएगा, और फिर STDERR को आउटपुट लिखेगा। जब हम इस आदेश को अपने निर्माण में डालते हैं, तो जैसा कि आप निर्दिष्ट करते हैं, हमें संदेश मिलता है।

$ { { echo a; sleep 10; echo >&2 b; } 2>&3 | \
    msgErr; } 3>&1 1>&2 | msgOut
STDERR: 2014-09-26 09:22:12 a
STDOUT: 2014-09-26 09:22:22 b

विधि # 2। एनोटेट-आउटपुट का उपयोग करना

एक उपकरण है जिसे पैकेज annotate-outputका हिस्सा कहा जाता है devscriptsजो आपको चाहिए। यह केवल प्रतिबंध है कि यह आपके लिए स्क्रिप्ट चलाने चाहिए।

उदाहरण

यदि हम अपने उपर्युक्त उदाहरण क्रम को एक स्क्रिप्ट में रखते हैं जिसे इस mycmds.bashप्रकार कहा जाता है:

$ cat mycmds.bash 
#!/bin/bash

echo a
sleep 10
echo >&2 b

हम इसे इस तरह से चला सकते हैं:

$ annotate-output ./mycmds.bash 
09:48:00 I: Started ./mycmds.bash
09:48:00 O: a
09:48:10 E: b
09:48:10 I: Finished with exitcode 0

आउटपुट के प्रारूप को टाइमस्टैम्प हिस्से के लिए नियंत्रित किया जा सकता है लेकिन उससे परे नहीं। लेकिन यह उसी तरह का आउटपुट है जैसा आप देख रहे हैं, इसलिए यह बिल फिट हो सकता है।


1
दुर्भाग्य से यह भी संभवतः कुछ लाइनों की अदला-बदली की समस्या को हल नहीं करता है।
पीटर

ठीक ठीक। मुझे लगता है कि मेरे इस सवाल का जवाब "संभव नहीं है"। stderredआपके साथ घटना आसानी से लाइनों की सीमाओं को निर्धारित नहीं कर सकती है (ऐसा करने से हैकिश होगा)। मैं यह देखना चाहता था कि क्या कोई मेरी इस समस्या में मदद कर सकता है, लेकिन जाहिर है कि हर कोई एकल बाधा ( आदेश ) को छोड़ना चाहता है, जो सवाल का आधार है
Deim0s

विधि 1 के चरण 2 को ठीक से काम करने के लिए मोर्चे पर एक और {की आवश्यकता है।
ऑस्टिन हैनसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.