कुछ कमांड अपने मानक इनपुट से क्यों नहीं पढ़ते हैं?


19

मुझे आश्चर्य है कि जब हमें पाइपलाइन का उपयोग करना चाहिए और जब हमें नहीं करना चाहिए।

उदाहरण के लिए, पीडीएफ फाइल को संभालने वाली कुछ प्रक्रिया को मारने के लिए, निम्नलिखित पाइपलाइन का उपयोग करके काम नहीं करेगा:

ps aux | grep pdf | awk '{print $2}'|kill

इसके बजाय, हम इसे निम्नलिखित तरीकों से कर सकते हैं:

kill $(ps aux| grep pdf| awk '{print $2}')

या

ps aux | grep pdf | awk '{print $2}'| xargs kill

के अनुसार man bash(संस्करण 4.1.2):

The standard output of command is connected via a pipe to the standard input of command2.

उपरोक्त परिदृश्य के लिए:

  • की स्टडआउट grepहै ps। यह काम करता है।
  • की स्टडआउट awkहै grep। यह काम करता है।
  • की स्टडआउट killहै awk। यह काम नहीं करता है।

पिछली कमांड के स्टडआउट से निम्न कमांड का स्टड हमेशा इनपुट प्राप्त कर रहा है।

  • क्यों यह साथ काम नहीं करता है killया rm?
  • बीच क्या अंतर है kill, rmसाथ इनपुट grep, awkइनपुट?
  • क्या कोई नियम हैं?

1
यह एक जवाब नहीं है, लेकिन आप पर एक नज़र है करने के लिए चाहते हो सकता है pgrep, pkillऔर killallआदेशों।
terdon

2
@terdon: मैं सिर्फ पाइपलाइन के मुद्दे को दिखाने के लिए ऊपर के परिदृश्य का उपयोग करता हूं, मैं समझता हूं कि pgrepऔर बाकी इसे पूरी तरह से प्राप्त कर सकते हैं :)
sylye

जवाबों:


17

कार्यक्रमों को इनपुट प्रदान करने के दो सामान्य तरीके हैं:

  • प्रक्रियाओं के STDIN को डेटा प्रदान करते हैं
  • कमांड लाइन तर्क निर्दिष्ट करें

killकेवल कमांड लाइन तर्क का उपयोग करता है। यह STDIN से नहीं पढ़ता है। एसटीडीआईएन (यदि कोई फ़ाइल नाम कमांड लाइन तर्क के रूप में नहीं दिया गया है) जैसे प्रोग्राम grepऔर awkपढ़े जाते हैं और डेटा को उनके कमांड लाइन तर्क (पैटर्न, स्टेटमेंट, फ्लैग, ...) के अनुसार प्रोसेस करते हैं।

आप केवल अन्य प्रक्रियाओं के एसटीडीआईएन पर पाइप कर सकते हैं, न कि लाइन तर्कों को कमांड करने के लिए।

सामान्य नियम यह है, कि प्रोग्राम डेटा की मनमानी मात्रा को संसाधित करने के लिए STDIN का उपयोग करता है। सभी अतिरिक्त इनपुट पैरामीटर या, यदि आमतौर पर केवल कुछ ही हैं, तो कमांड लाइन तर्क द्वारा पारित किए जाते हैं। यदि कमांड लाइन बहुत लंबी हो सकती है, उदाहरण के लिए लंबे awkप्रोग्राम ग्रंथों के लिए, अक्सर अतिरिक्त प्रोग्राम फ़ाइलों (इनका -fविकल्प awk) से इन्हें पढ़ने की संभावना है ।

कमांड लाइन के तर्कों के रूप में कार्यक्रमों के STDOUT का उपयोग करने के लिए, $(...)या बहुत सारे डेटा के मामले में उपयोग करें xargsfindइसके साथ सीधे भी कर सकते हैं -exec ... {} +

पूर्णता के लिए: STDOUT को कमांड लाइन तर्क लिखने के लिए, उपयोग करें echo


1
हम कैसे जानते हैं कि एक कमांड केवल तर्क लेगा लेकिन एसटीडीआईएन नहीं। क्या मैन पेज से अनुमान लगाने या पढ़ने के बजाय एक व्यवस्थित या प्रोग्रामेटिक तरीका है? केवल मैन पेज को पढ़ने से, मैं इस बात पर दृढ़ रहने के लिए कोई विशेष सुराग नहीं प्राप्त कर सकता था कि क्या कमांड एसटीडीआईएन ले सकता है या नहीं ले सकता, क्योंकि एसटीडीआईएन भी उस तरह से तर्कों का हिस्सा है जिस तरह से एक आदमी पेज मौजूद है। उदाहरण के लिए, gzipSYNOPSIS में, यह नहीं कहा कि इसे इनपुट के रूप में एक FILENAME लेना होगा। मैं देख रहा हूँ कि यह निर्धारित करने के लिए एक अधिक व्यवस्थित तरीका है।
11

कुछ आज्ञाओं के लिए "-" तर्क भी है जिसका अर्थ है "स्टडिन" (या "स्टडआउट")।
इमैनुएल

xargsठीक से आपको "लाइन टू कमांड लाइन तर्क" की अनुमति नहीं देगा?
टी। वेरॉन

@ T.Verron हाँ, यह कार्य है xargs। यह कमांड को बुलाता है यदि आवश्यक हो तो एक से अधिक बार (कमांड लाइन का आकार सीमित है) और बहुत सारे अन्य विकल्प हैं।
जोफेल

2
विवरण का पाठ वर्णन करेगा कि आप कार्यक्रम का उपयोग कैसे कर सकते हैं। उदाहरण के लिए, gzip कहता है: "gzip प्रोग्राम Lempel-Ziv कोडिंग (LZ77) का उपयोग करके फ़ाइलों को संकुचित और विघटित करता है। यदि कोई फ़ाइल निर्दिष्ट नहीं है, तो gzip मानक इनपुट, या decompress से मानक आउटपुट तक संपीड़ित करेगा।" यदि कोई पुरुष पृष्ठ मानक इनपुट का उल्लेख नहीं करता है, तो वह इसका उपयोग नहीं करेगा।
एलन शटको

16

यह एक दिलचस्प सवाल है, और यह यूनिक्स / लिनक्स दर्शन के एक हिस्से से संबंधित है।

तो, जैसे कार्यक्रमों के बीच अंतर क्या है grep, sed, sortएक हाथ पर और kill, rm, lsदूसरी ओर? मुझे दो पहलू दिखाई देते हैं।

फिल्टर पहलू

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

  • दूसरे प्रकार के प्रोग्राम एक इनपुट पर कार्य करते हैं, लेकिन जो आउटपुट वे देते हैं वह अक्सर इनपुट से संबंधित नहीं होता है। killइसका कोई आउटपुट नहीं है जब यह नियमित रूप से काम करता है, न तो करता है ls। सफलता दिखाने के लिए बस एक वापसी मूल्य है। वे आम तौर पर STDIN से इनपुट नहीं लेते हैं, लेकिन ज्यादातर STDOUT को आउटपुट देते हैं।

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

अर्थ पहलू

  • फ़िल्टर के लिए, उनके इनपुट का कोई अर्थ नहीं है । वे सिर्फ डेटा पढ़ते हैं, डेटा, आउटपुट डेटा को संशोधित करते हैं। इससे कोई फर्क नहीं पड़ता कि यह संख्यात्मक मानों की सूची है, कुछ फ़ाइलनाम या HTML स्रोत कोड। इस डेटा का अर्थ केवल आपको फ़िल्टर प्रदान करने वाले कोड द्वारा दिया गया है : regex for grep, के लिए नियम awkया पर्ल प्रोग्राम।

  • अन्य कार्यक्रमों के लिए, जैसे killया ls, उनके इनपुट का एक अर्थ है , एक डिनोटेशनkillअपेक्षाएँ संख्याएँ, lsफ़ाइल या पथ नामों की अपेक्षा करती हैं। वे मनमाने डेटा को संभाल नहीं सकते हैं और वे करने के लिए नहीं हैं। उनमें से कई को किसी भी इनपुट या मापदंडों की आवश्यकता नहीं है, जैसे ps। वे आम तौर पर STDIN से नहीं पढ़ते हैं।

एक शायद इन दो पहलुओं को जोड़ सकता है: एक फिल्टर एक प्रोग्राम है जिसका इनपुट प्रोग्राम के लिए अर्थ अर्थ नहीं है।

मुझे यकीन है कि मैंने इस दर्शन के बारे में कहीं पढ़ा है, लेकिन मुझे फिलहाल कोई स्रोत याद नहीं है, क्षमा करें। यदि किसी के पास कुछ स्रोत मौजूद हैं, तो कृपया बेझिझक संपादित करें।


5

ऐसे कोई "नियम" नहीं हैं। कुछ प्रोग्राम एसटीडीआईएन से इनपुट लेते हैं, और कुछ नहीं करते हैं। यदि कोई प्रोग्राम STDIN से इनपुट ले सकता है, तो उसे पाइप किया जा सकता है, यदि नहीं, तो यह नहीं हो सकता।

आप आम तौर पर बता सकते हैं कि कोई प्रोग्राम इनपुट करेगा या नहीं इसके बारे में सोचकर कि यह क्या करता है। कार्यक्रम की नौकरी किसी भी तरह हेरफेर करने के लिए है, तो सामग्री एक फ़ाइल (जैसे की grep, sed, awkआदि), यह सामान्य रूप से STDIN से इनपुट लेता है। अपना काम फ़ाइल स्वयं (जैसे हेरफेर करने के लिए है, तो mv, rm, cp) या एक प्रक्रिया (उदाहरण के लिए kill, lsof) या कुछ और के बारे में वापसी के बारे में जानकारी के लिए (उदाहरण के लिए top, find, ps) तो ऐसा नहीं होता।

इसके बारे में सोचने का एक और तरीका तर्क और इनपुट के बीच का अंतर है। उदाहरण के लिए:

mv foo bar

ऊपर दिए गए कमांड में, mvइस तरह का कोई इनपुट नहीं है। जो दिया गया है, वह दो तर्क है। यह पता नहीं है या परवाह नहीं है कि दोनों फाइलों में क्या है, यह सिर्फ जानता है कि वे इसके तर्क हैं और यह उन्हें हेरफेर करना चाहिए।

दूसरी ओर

sed -e 's/foo/bar/' < file
--- -- ------------   ----
 |   |       |          |-> input
 |   |       |------------> argument        
 |   |--------------------> option/flag/switch
 |------------------------> command

यहाँ, sedइनपुट के साथ-साथ एक तर्क भी दिया गया है। चूंकि यह इनपुट लेता है, इसलिए इसे STDIN से पढ़ा जा सकता है और इसे पाइप किया जा सकता है।

यह अधिक जटिल हो जाता है जब एक तर्क इनपुट हो सकता है। उदाहरण के लिए

cat file

यहाँ, fileवह तर्क है जिसे दिया गया था cat। सटीक होने के लिए, फ़ाइल नाम file तर्क है। हालाँकि, चूंकि catएक प्रोग्राम है जो फ़ाइलों की सामग्री में हेरफेर करता है, इसका इनपुट जो कुछ भी अंदर है file

यह straceएक प्रोग्राम का उपयोग करके सचित्र किया जा सकता है , जो प्रक्रियाओं द्वारा किए गए सिस्टम कॉल को ट्रैक करता है। अगर हम चलाने cat fooके माध्यम से strace, हम देख सकते हैं कि फ़ाइल fooखोला है:

$ strace cat foo 2| grep foo
execve("/bin/cat", ["cat", "foo"], [/* 44 vars */]) = 0
open("foo", O_RDONLY)     

शो के ऊपर पहली पंक्ति है कि कार्यक्रम /bin/catबुलाया गया था और अपने तर्कों थे catऔर foo(पहला तर्क हमेशा कार्यक्रम में ही है)। बाद में, तर्क fooकेवल मोड में पढ़ा गया था। अब, इसके साथ तुलना करें

$ strace ls foo 2| grep foo 
execve("/bin/ls", ["ls", "foo"], [/* 44 vars */]) = 0
stat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
lstat("foo", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
write(1, "foo\n", 4foo

यहाँ भी, lsखुद को और fooतर्कों के रूप में लिया । हालांकि, कोई openकॉल नहीं है , तर्क को इनपुट के रूप में नहीं माना जाता है। इसके बजाय, फ़ाइल के बारे में जानकारी प्राप्त करने के लिए lsसिस्टम के statपुस्तकालय (जो statकमांड जैसी ही चीज नहीं है ) को कॉल करता है foo

सारांश में, यदि आप जो कमांड चला रहे हैं, वह इसके इनपुट को पढ़ेगा, तो आप इसे पाइप कर सकते हैं, यदि यह नहीं है, तो आप नहीं कर सकते।


0
  • यह मार या आरएम के साथ काम क्यों नहीं करता है?

killऔर rmSTDIN की जरूरत नहीं है।

  • Grep, awk input के साथ किल, आरएम इनपुट के बीच क्या अंतर है?

के लिए killऔर rm, उन तर्क के रूप में उनके अनुकूलित जानकारी प्रदान करते हैं, और $(cmd)के STDOUT लेने में मदद करता है cmdऔर यह जानकारी तर्क परिवर्तित।

के लिए grepऔर awk, उन तर्कों और इसके अलावा, यह भी प्रदान करते हैं STDINया एक नियमित रूप से फ़ाइल है कि आदेश से कार्रवाई की जाएगी। STDINपाइपलाइन के साथ |या मैन्युअल रूप से इनपुट करके पारित किया जा सकता है ।

  • क्या कोई नियम हैं?

मैनुअल या सोर्स कोड पढ़ें। और अगर आपको कुछ भी नहीं चाहिए, तो आप एक सरल लेकिन शायद खतरनाक परीक्षण कर सकते हैं:

केवल उस कमांड को इनपुट करें जिसके बारे में आप उत्सुक हैं, उन तर्कों के साथ जिन्हें आप पहले ही समझ चुके हैं, और देखें कि क्या कमांड पॉज़ करता है (कुछ नहीं होता)। यदि यह रोकते हैं, यह वास्तव में (तुम कोशिश कर सकते STDIN के लिए इंतज़ार कर रहा है catऔर echoअलग अलग देखने के लिए)। आप मैन्युअल रूप से टाइप करते हैं Ctrl-Dऔर कमांड आगे बढ़ता है (परिणाम या त्रुटियां दिखाता है) और रिटर्न करता है। इस तरह के कमांड को उस स्थिति में STDIN की आवश्यकता होती है (आपके द्वारा प्रदान किए गए तर्कों के साथ)।

एक ही कमांड को अलग-अलग स्थितियों में STDIN की आवश्यकता नहीं हो सकती है (जैसे, catSTDIN की प्रतीक्षा करता है , लेकिन cat file.txtनहीं)।

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