मैं जीआरई को रीडायरेक्ट करने के लिए टी का उपयोग कैसे करूं


13

मुझे टी का उपयोग करने का अधिक अनुभव नहीं है, इसलिए मुझे उम्मीद है कि यह बहुत बुनियादी नहीं है।

इस सवाल का एक जवाब देखने के बाद मैं एक अजीब सा व्यवहार करने लगा tee

मेरे लिए पहली पंक्ति, और एक मिली लाइन का उत्पादन करने के लिए, मैं इसका उपयोग कर सकता हूं:

ps aux | tee >(head -n1) | grep syslog
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4

हालाँकि, पहली बार जब मैंने इसे (zsh में) चलाया तो परिणाम गलत क्रम में था, कॉलम हेडर grep परिणामों से नीचे थे (हालांकि यह फिर से नहीं हुआ), इसलिए मैंने चारों ओर कमांड स्वैप करने की कोशिश की:

ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

केवल पहली पंक्ति ही छपी है, और कुछ नहीं! क्या मुझे टीआरई का उपयोग जीआरईपी पर पुनर्निर्देशित करने के लिए किया जा सकता है, या क्या मैं गलत तरीके से कर रहा हूं?

जैसा कि मैं इस प्रश्न को टाइप कर रहा था, दूसरी कमांड ने वास्तव में मेरे लिए एक बार काम किया, मैंने इसे पांच बार फिर से चलाया और फिर एक पंक्ति के परिणाम पर वापस आ गया। क्या यह सिर्फ मेरी व्यवस्था है? (मैं tmux के भीतर zsh चला रहा हूं)।

अंत में, पहले कमांड के साथ "grep syslog" को परिणाम के रूप में क्यों नहीं दिखाया गया है (केवल एक परिणाम है)?

नियंत्रण के लिए यहाँ बिना grep है tee

ps aux | grep syslog
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4
henry    2290  0.0  0.1  95220  3092 ?        Ssl  Sep07   3:12 /usr/bin/pulseaudio --start --log-target=syslog
henry   15924  0.0  0.0   3128   824 pts/4    S+   13:44   0:00 grep syslog

अद्यतन: ऐसा लगता है कि सिर पूरी कमांड को कम करने का कारण बन रहा है (जैसा कि नीचे दिए गए उत्तर में दर्शाया गया है) नीचे दी गई कमांड अब वापस आ रही है:

ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
syslog     806

आपके प्रश्न का सीधा उत्तर नहीं है, लेकिन ऐसा कुछ करने के लिए बहुत क्लीनर होगा ps aux | sed -n -e '1p' -e '/syslog/p'
jw013

मैंने कभी भी sed के बारे में नहीं सोचा था, मुझे लगता है कि यहाँ संबंधित प्रश्न के लिए एक उपयुक्त उत्तर हो सकता है, लेकिन मैं वास्तव में इन आज्ञाओं के असंगत व्यवहार के बारे में जानकारी की तलाश में हूँ!
15 मई को Rqomey

जवाबों:


19
$ ps aux | tee >(head -n1) | grep syslog
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND 
syslog     806  0.0  0.0  34600   824 ?        Sl   Sep07   0:00 rsyslogd -c4

grepऔर headआदेशों लगभग उसी समय शुरू करते हैं, और दोनों का अपना खाली समय में एक ही इनपुट डेटा प्राप्त करते हैं, लेकिन आम तौर पर, के रूप में डेटा उपलब्ध हो जाता है। कुछ चीजें हैं जो 'अनसिंक्रनाइज़्ड' आउटपुट को पेश कर सकती हैं जो लाइनों को फ़्लिप करती हैं; उदाहरण के लिए:

  1. बहुप्रचलित डेटा teeवास्तव में एक प्रक्रिया से दूसरे के पहले भेजा जाता है, जो मुख्य रूप से कार्यान्वयन पर निर्भर करता है tee। एक सरल teeकार्यान्वयन readकुछ मात्रा में इनपुट करेगा, और फिर writeदो बार: एक बार स्टडआउट और एक बार अपने तर्क के लिए। इसका मतलब है कि उन गंतव्यों में से एक को पहले डेटा मिलेगा।

    हालांकि, पाइप सभी बफर्ड हैं। यह संभावना है कि ये बफ़र प्रत्येक 1 पंक्ति के हैं, लेकिन वे बड़े हो सकते हैं, जो प्राप्त कमांडों में से एक को आउटपुट के लिए आवश्यक सब कुछ देखने के लिए पैदा कर सकता है (यानी grepपेड लाइन) अन्य कमांड से पहले ( head) में कोई भी डेटा प्राप्त हुआ है। सब।

  2. उपरोक्त के बावजूद, यह भी संभव है कि इनमें से एक कमांड डेटा प्राप्त करता है, लेकिन समय के साथ इसके साथ कुछ भी करने में असमर्थ है, और फिर अन्य कमांड अधिक डेटा प्राप्त करता है और इसे जल्दी से संसाधित करता है।

    उदाहरण के लिए, भले ही headऔर grepअगर, एक समय में डेटा एक पंक्ति भेजा जाता है headइसके साथ सौदा करने के लिए कैसे (या कर्नेल शेड्यूलिंग की देरी हो जाता है) पता नहीं है, grepउसके परिणामों से पहले दिखा सकते हैं headयहां तक कि के लिए एक मौका हो जाता है। प्रदर्शित करने के लिए, एक देरी जोड़ने का प्रयास करें: ps aux | tee >(sleep 1; head -n1) | grep syslogयह निश्चित रूप से grepपहले आउटपुट का उत्पादन करेगा ।

$ ps aux | tee >(grep syslog) | head -n1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

मेरा मानना ​​है कि आप अक्सर यहां केवल एक लाइन headप्राप्त करते हैं, क्योंकि इनपुट की पहली पंक्ति प्राप्त होती है और फिर इसकी स्टडिन को बंद कर देता है। जब teeदेखता है कि इसका स्टडआउट बंद कर दिया गया है, तो यह अपने स्वयं के स्टड (आउटपुट से ps) को बंद कर देता है और बाहर निकल जाता है। यह कार्यान्वयन-निर्भर हो सकता है।

प्रभावी रूप से, एकमात्र डेटा जो psभेजने के लिए मिलता है, वह पहली पंक्ति है (निश्चित रूप से, क्योंकि headइस पर नियंत्रण है), और हो सकता है कि कुछ अन्य पंक्तियाँ पहले headऔर teeउनके स्टड डिस्क्रिप्टर को बंद कर दें।

दूसरी पंक्ति प्रकट होने के साथ असंगतता समय द्वारा पेश की गई है: headस्टड को बंद कर देती है , लेकिन psअभी भी डेटा भेज रही है। ये दो घटनाएँ अच्छी तरह से सिंक्रनाइज़ नहीं हैं, इसलिए लाइन वाली लाइन syslogअभी भी इसे teeतर्क ( grepकमांड) बनाने का एक मौका है । यह ऊपर दिए गए स्पष्टीकरण के समान है।

आप कमांड का उपयोग करके इस समस्या से पूरी तरह से बच सकते हैं जो स्टड / बाहर निकलने से पहले सभी इनपुट की प्रतीक्षा करते हैं। उदाहरण के लिए, awkइसके बजाय का उपयोग करें head, जो अपनी सभी लाइनों को पढ़ेगा और संसाधित करेगा (भले ही वे कोई आउटपुट न दें):

ps aux | tee >(grep syslog) | awk 'NR == 1'

लेकिन ध्यान दें कि लाइनें अभी भी ऊपर-नीचे के रूप में दिखाई दे सकती हैं, जो कि निम्न द्वारा प्रदर्शित की जा सकती हैं:

ps aux | tee >(grep syslog) | (sleep 1; awk 'NR == 1')

आशा है कि यह बहुत अधिक विस्तार नहीं था, लेकिन एक-दूसरे के साथ बातचीत करने वाली बहुत सी चीजें हैं। अलग-अलग प्रक्रियाएं बिना किसी तुल्यकालन के एक साथ चलती हैं, इसलिए किसी विशेष रन पर उनकी क्रियाएं अलग-अलग हो सकती हैं; कभी-कभी यह समझाने के लिए अंतर्निहित प्रक्रियाओं में गहरी खुदाई करने में मदद करता है कि क्यों।


1
बहुत बढ़िया जवाब! मैंने वास्तव में पूछा क्योंकि मैं अंतर्निहित प्रक्रियाओं में रुचि रखता हूं। जब चीजें स्पष्ट होती हैं तो मुझे यह दिलचस्प लगता है। क्या चलाने का एक बेहतर तरीका ps aux | tee >(grep syslog) | head -n1होगा जो headस्टडआउट को बंद कर देगा । वाह, इस कमांड ने अब आउटपुट देना शुरू कर दिया है, लेकिन जैसा कि आपके उत्तर के अनुरूप होगा, यह छोटा प्रतीत होता हैUSER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND syslog 806
Rqomey

1
आप कुछ का उपयोग कर सकते हैं जो स्टडिन के बजाय बंद नहीं करता है head। मैंने इस उदाहरण के साथ उत्तर को अपडेट किया है:ps aux | tee >(grep syslog) | awk 'NR == 1'
mrb

1
@KrzysztofAdamski, जब आप उपयोग करते हैं >(cmd), तो शेल एक नामित पाइप बनाता है और कमांड के तर्क के रूप में पास करता है ( tee)। तब teestdout को लिखा जाता है (पाइप किया गया awk) और उस तर्क को भी। यह mkfifo a_fifo ; grep ... a_fifoएक शेल में और ps | tee a_fifo | awk ...दूसरे में समान है।
mrb

1
@KrzysztofAdamski gnu.org/software/bash/manual/html_node/... - कोशिश करें echo >(exit 0), जो वास्तविक तर्क खोल द्वारा पारित गूंज जाएगा (मेरे मामले में, यह हो जाता है /dev/fd/63)। यह बाश और zsh पर एक ही काम करना चाहिए।
mrb

1
@ mrb: यह बहुत ही दिलचस्प विशेषता है जो मुझे पहले नहीं पता था, धन्यवाद। यह कुछ अजीब तरीके से काम कर रहा है, हालाँकि, pastebin.com/xFgRcJdF देखें । दुर्भाग्य से मेरे पास अब इसकी जांच करने का समय नहीं है लेकिन मैं इसे कल करूंगा।
क्रेजिसटेस्टोफ़ एडामस्की

2

grep syslogहमेशा नहीं दिखाया जाता है क्योंकि यह समय पर निर्भर करता है। शेल पाइपलाइन का उपयोग करते समय, आप लगभग एक साथ कमांड चला रहे हैं। लेकिन यहां महत्वपूर्ण बात "लगभग" शब्द है। अगर psgrep लॉन्च होने से पहले सभी प्रक्रियाओं को स्कैन कर लिया जाए, तो यह सूची में नहीं होगा। आप सिस्टम के भार आदि के आधार पर यादृच्छिक परिणाम प्राप्त कर सकते हैं।

आपके टी के साथ भी ऐसा ही होता है। यह पृष्ठभूमि में उपधारा में चलाया जाता है और इसे grep से पहले या बाद में निकाल दिया जा सकता है। यही कारण है कि आउटपुट ऑर्डर असंगत है।

टी सवाल के रूप में, यह व्यवहार काफी अजीब है। ऐसा इसलिए है क्योंकि इसका उपयोग सामान्य तरीके से नहीं किया जाता है। यह बिना किसी तर्क के चलाया जाता है, जिसका अर्थ है कि इसे स्टडआउट से स्टडआउट तक सिर्फ डेटा कॉपी करना चाहिए। लेकिन यह stdout को चल रहे सिर (पहले मामले में) या grep (2 के मामले) को पुनः निर्देशित करने के लिए पुनर्निर्देशित किया गया है। लेकिन यह अगले कमांड पर भी लगा होता है। मुझे लगता है कि इस मामले में क्या होता है वास्तव में कार्यान्वयन निर्भर है। उदाहरण के लिए मेरे बैश ४.२.२, पर, कुछ भी कभी भी स्टड को सब्मिट करने के लिए नहीं लिखा जाता है। Zsh पर, यह विश्वसनीय तरीके से काम करता है जो आप चाहते हैं (पीएस की पहली पंक्ति और खोज की गई दोनों पंक्तियों को मुद्रित करना), हर बार जब मैं कोशिश करता हूं,


वैसे भी एक बात समझाता है, मुझे आश्चर्य है कि टी देरी grep एक ध्यान देने योग्य हद तक चल रहा है!
रकॉमी

0

एक बिट हैकिश, लेकिन यहाँ एक psgrep()शेल फ़ंक्शन के रूप में मेरा समाधान है :

पुन: निर्देशित psकरने के लिए शीर्ष लेख पंक्ति STDERRहै, तो grepपर STDOUTहै, लेकिन पहले हटाने के grepआदेश ही है, 'शोर' पंक्ति से उत्पन्न से बचने के लिए grepखुद को:

psgrep() { ps aux | tee >(head -1>&2) | grep -v " grep $@" | grep "$@" -i --color=auto; }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.