टार टू पाइप लेकिन Keep -v वर्बोज़ आउटपुट STDERR से अलग


12

एक सामान्य टार कमांड

tar cvf foo.tar ./foo >foo.out 2>foo.err

तीन आउटपुट IO स्ट्रीम है

  • संग्रह डेटा foo.tar को
  • फ़ाइल नाम की सूची STDOUT (foo.out में पुनर्निर्देशित)
  • STDERR को त्रुटि संदेश (foo.err में पुनर्निर्देशित)

फिर मैं फ़ाइल नाम की सूची के माध्यम से पढ़ने के लिए बिना त्रुटि संदेशों के foo.err का निरीक्षण कर सकता हूं।

अगर मैं संग्रह डेटा के साथ कुछ करना चाहता हूं (इसे netcat या एक विशेष संपीड़न प्रोग्राम के माध्यम से पाइप करें) मैं -f -इस प्रकार टार के विकल्प का उपयोग कर सकता हूं

tar cvf - ./foo 2>foo.err | squish > foo.tar.S

लेकिन अब मेरी फ़ाइल नाम की सूची में मेरे त्रुटि संदेशों के साथ मिलाया गया है क्योंकि टार का -vआउटपुट स्पष्ट रूप से STDOUT पर नहीं जा सकता है (यह वह जगह है जहाँ संग्रह डेटा बहता है) इसलिए टार चतुराई से लिखता है कि बजाय STDERR को।

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


क्या आप परिचित हैं tee? यह इसके लिए एक बहुत वैध उपयोग के मामले जैसा लगता है।
हेलोजॉस्ट

जवाबों:


9

यदि आपका सिस्टम समर्थन करता है /dev/fd/n:

tar cvf /dev/fd/3 ./foo 3>&1 > foo.out 2>foo.err | squish > foo.tar.S

प्रक्रिया प्रतिस्थापन के उपयोग से आप ksh( bashया zsh) के एटी एंड टी कार्यान्वयन के साथ कौन से लिख सकते हैं :

tar cvf >(squish > foo.tar.S) ./foo > foo.out 2>foo.err

इस समय को छोड़कर वही काम कर रहा है, शेल किस फाइल डिस्क्रिप्टर का उपयोग करने का निर्णय लेता है 3(आमतौर पर 9 से ऊपर) के बजाय । एक और अंतर यह है कि इस बार, आपको tarइसके बजाय बाहर निकलने की स्थिति मिलती है squish। सिस्टम पर जो समर्थन नहीं करते हैं /dev/fd/n, कुछ शेल उस सुविधा के लिए नामित पाइप का सहारा ले सकते हैं।

यदि आपका सिस्टम समर्थन नहीं करता है /dev/fd/nया आपका शेल इसकी प्रक्रिया के प्रतिस्थापन के लिए नामित पाइपों का उपयोग नहीं कर सकता है, तो आपको हाथ से नामित पाइपों से निपटना होगा


6

आपको उसके लिए एक नामित पाइप का उपयोग करना होगा।

पहले फ़ोल्डर में एक बनाएँ:

mkfifo foo.pipe

फिर उस कमांड का उपयोग करें:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & cat foo.pipe >foo.tar

नोटिस:cat भाग, अब भी हो सकता है gzipया जो कुछ भी है कि एक पाइप से पढ़ सकते हैं:

tar cvf foo.pipe ./foo >foo.out 2>foo.err & gzip -c foo.pipe >foo.tar

स्पष्टीकरण:

उत्पादन नाम पाइप (करने के लिए लिखा है foo.pipe), जहां एक और प्रक्रिया ( cat, gzip, netcat) से पढ़ता है। तो आप जानकारी के लिए stdout / stderr चैनल को ढीला न करें।


1
नामित पाइप का उपयोग करने के निहितार्थ को ध्यान देने योग्य हो सकता है । 1) सबसे अच्छा यह है कि umask 077(या एक निजी अस्थायी डीआईआर का उपयोग करें) इसे पढ़ने या लिखने की अन्य प्रक्रियाओं को रोकने के लिए (कई प्रणालियों पर, नामित पाइप, जैसे अन्य फाइलें डिफ़ॉल्ट रूप से विश्व-पठनीय बनाई जाती हैं), 2) आपको यह सुनिश्चित करने की आवश्यकता है नामित पाइप का उपयोग केवल आपकी स्क्रिप्ट के प्रत्येक उदाहरण द्वारा किया जाता है (फिर से एक-एक निजी अस्थायी निर्देशिका में मदद करता है) 3) इसका मतलब है कि आपको बाद में या अगर बाधित करने की आवश्यकता है।
स्टीफन चेजलस

1
+1 - मुझे यह उत्तर पसंद है। दुर्भाग्य से मेरे लिए, मेरे (पुराने) सिस्टम पर नामित पाइपों में कुछ अजीबता है जो मुझे यह कोशिश करने पर अविश्वसनीय बनाती है।
RedGrittyBrick

1
@ स्टीफनचेज़ेलैस - मुझे लगता है कि कभी-कभी पहले सफाई करना आसान हो सकता है, जैसे:p="/tmp/pipe$$"; mkfifo "$p"; (read na; cmd[s]...) <>"$p" & (echo;rm "$p"; cmd[s]...) >"$p"
mikeserv

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