প্রক্রিয়া বিকল্প এবং পাইপ


86

আমি কীভাবে নিম্নলিখিতটি বুঝতে পারি তা ভাবছিলাম:

অন্যের স্টিডিনে কমান্ডের stdout পাইপ করা একটি শক্তিশালী কৌশল। তবে, যদি আপনার একাধিক কমান্ডের স্টাডআউটটি পাইপ করা দরকার? প্রক্রিয়া প্রতিস্থাপনটি এখানে আসে।

অন্য কথায়, প্রতিস্থাপন প্রক্রিয়া পাইপ যা করতে পারে তা করতে পারে?

প্রতিস্থাপনের প্রক্রিয়া কী করতে পারে তবে পাইপ পারে না?

উত্তর:


133

তাদের মধ্যে পার্থক্য ছড়িয়ে দেওয়ার একটি ভাল উপায় হ'ল কমান্ড লাইনে সামান্য পরীক্ষা-নিরীক্ষা করা। <চরিত্রটির ব্যবহারের ক্ষেত্রে চাক্ষুষ মিল থাকলেও এটি পুনর্নির্দেশ বা পাইপের চেয়ে খুব আলাদা কিছু করে।

dateপরীক্ষার জন্য কমান্ডটি ব্যবহার করা যাক ।

$ date | cat
Thu Jul 21 12:39:18 EEST 2011

এটি একটি অর্থহীন উদাহরণ তবে এটি এটি দেখায় যে এসটিডিআইএন-এর catআউটপুট গ্রহণ করেছে dateএবং এটি পিছনে থুথু দিয়েছে। প্রক্রিয়া প্রতিস্থাপনের মাধ্যমে একই ফলাফল অর্জন করা যেতে পারে:

$ cat <(date)
Thu Jul 21 12:40:53 EEST 2011

তবে পর্দার আড়ালে যা ঘটেছিল তা ভিন্ন ছিল। STDIN স্ট্রিম দেওয়ার পরিবর্তে catআসলে এমন কোনও ফাইলের নাম দেওয়া হয়েছিল যা এটি খোলার জন্য এবং পড়তে হবে। echoপরিবর্তে ব্যবহার করে আপনি এই পদক্ষেপটি দেখতে পারেন cat

$ echo <(date)
/proc/self/fd/11

বিড়াল যখন ফাইলটির নাম পেয়েছিল, তখন এটি আমাদের জন্য ফাইলের সামগ্রীটি পড়ে। অন্যদিকে, প্রতিধ্বনি আমাদের কেবল ফাইলটির নাম দেখিয়েছিল যে এটি পাস হয়ে গেছে। এই পার্থক্যটি আরও সুস্পষ্ট হয়ে ওঠে যদি আপনি আরও বিকল্পগুলি যুক্ত করেন:

$ cat <(date) <(date) <(date)
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011
Thu Jul 21 12:44:45 EEST 2011

$ echo <(date) <(date) <(date)
/proc/self/fd/11 /proc/self/fd/12 /proc/self/fd/13

প্রক্রিয়া বিকল্প (যা একটি ফাইল উত্পন্ন করে) এবং ইনপুট পুনঃনির্দেশ (যা কোনও ফাইলকে এসটিডিআইএন-এর সাথে সংযুক্ত করে) একত্রিত করা সম্ভব:

$ cat < <(date)
Thu Jul 21 12:46:22 EEST 2011

দেখতে দেখতে অনেকটা একইরকম কিন্তু এবার বিড়ালটিকে কোনও ফাইলের নামের পরিবর্তে STDIN প্রবাহটি দেওয়া হয়েছিল। প্রতিধ্বনি দিয়ে চেষ্টা করে দেখতে পারেন:

$ echo < <(date)
<blank>

যেহেতু প্রতিধ্বনি STDIN পড়ে না এবং কোনও যুক্তি পাস করা হয় না, তাই আমরা কিছুই পাই না।

পাইপ এবং ইনপুট পুনঃনির্দেশগুলি STDIN স্ট্রিমের মধ্যে সামগ্রী সরিয়ে দেয়। প্রক্রিয়া প্রতিস্থাপন কমান্ডগুলি চালায়, তাদের আউটপুট একটি বিশেষ অস্থায়ী ফাইলে সংরক্ষণ করে এবং তারপরে সেই ফাইলটির নাম কমান্ডের জায়গায় পাস করে। আপনি যে কমান্ড ব্যবহার করছেন তা ফাইলের নাম হিসাবে বিবেচনা করে। মনে রাখবেন যে তৈরি করা ফাইলটি কোনও নিয়মিত ফাইল নয় তবে নামযুক্ত পাইপ যা একবার আর প্রয়োজন হয় না তা স্বয়ংক্রিয়ভাবে মুছে ফেলা হয়।


আমি যদি ভালভাবে বুঝতে পারি, tldp.org/LDP/abs/html/process-sub.html#FTN.AEN18244 বলে যে প্রক্রিয়া প্রতিস্থাপনটি পাইপ নয়, অস্থায়ী ফাইল তৈরি করে। যতদূর আমি জানি নামগুলি অস্থায়ী ফাইল তৈরি করে না। পাইপে লিখতে কখনই ডিস্কে লিখন জড়িত না: stackoverflow.com/a/6977599/788700
অ্যাডোব

আমি জানি এই উত্তরটি 'পাঠ্য হয় কারণ এটা শব্দ ব্যবহার grok : ডি
aqn

2
@Adobe তা নিশ্চিত করতে পারি অস্থায়ী ফাইল প্রক্রিয়া প্রতিকল্পন উৎপন্ন সঙ্গে একটি নামে পাইপ হল: [[ -p <(date) ]] && echo true। এটি তৈরি করে trueযখন আমি এটি 4.4 বা 3.2 বাশ দিয়ে চালাই।
দে নভো

24

আমার ধারণা করা উচিত যে আপনি bashবা অন্য কোনও উন্নত শেলের কথা বলছেন , কারণ পিক্সিক শেলটির প্রক্রিয়া বিকল্প নেই

bash ম্যানুয়াল পৃষ্ঠা রিপোর্ট:

প্রক্রিয়া প্রতিস্থাপন
প্রক্রিয়া প্রতিস্থাপন সিস্টেমগুলিতে সমর্থিত যা নামক পাইপ (FIFOs) বা খোলা ফাইলগুলির নামকরণের / dev / fd পদ্ধতি সমর্থন করে। এটি <(তালিকা) বা> (তালিকা) এর রূপ নেয়। প্রক্রিয়া তালিকাটি কোনও FIFO বা / dev / fd- তে কোনও ফাইলের সাথে সংযুক্ত তার ইনপুট বা আউটপুট দিয়ে চালিত হয়। এই ফাইলটির নাম প্রসারণের ফলস্বরূপ বর্তমান কমান্ডের যুক্তি হিসাবে পাস করা হয়েছে। যদি> (তালিকা) ফর্মটি ব্যবহার করা হয় তবে ফাইলটিতে লিখিতভাবে তালিকার জন্য ইনপুট সরবরাহ করা হবে। <(তালিকা) ফর্মটি ব্যবহার করা হলে, আর্গুমেন্ট হিসাবে পাস করা ফাইলটি তালিকার আউটপুট পেতে পাঠ করা উচিত।

যখন উপলব্ধ হয়, প্রক্রিয়া প্রতিস্থাপন প্যারামিটার এবং ভেরিয়েবল সম্প্রসারণ, কমান্ড প্রতিস্থাপন এবং পাটিগণিত সম্প্রসারণ একযোগে সঞ্চালিত হয়।

অন্য কথায়, এবং ব্যবহারিক দৃষ্টিকোণ থেকে, আপনি নিম্নলিখিত মত একটি অভিব্যক্তি ব্যবহার করতে পারেন

<(commands)

প্যারামিটার হিসাবে একটি ফাইলের প্রয়োজন অন্য কমান্ডগুলির জন্য ফাইলের নাম হিসাবে। অথবা আপনি যেমন একটি ফাইলের জন্য পুনঃনির্দেশ ব্যবহার করতে পারেন:

while read line; do something; done < <(commands)

আপনার প্রশ্নের দিকে ফিরে যাওয়া, আমার কাছে মনে হয় প্রক্রিয়া প্রতিস্থাপন এবং পাইপগুলির মধ্যে খুব একটা মিল নেই।

আপনি যদি একাধিক কমান্ডের আউটপুটকে একত্রে পাইপ করতে চান তবে নীচের ফর্মগুলির মধ্যে একটি ব্যবহার করতে পারেন:

(command1; command2) | command3
{ command1; command2; } | command3

তবে আপনি প্রক্রিয়া প্রতিস্থাপনে পুনঃনির্দেশও ব্যবহার করতে পারেন

command3 < <(command1; command2)

অবশেষে, যদি command3কোনও ফাইল প্যারামিটার গ্রহণ করা হয় (স্টিডিনের পরিবর্তে)

command3 <(command1; command2)

সুতরাং <() এবং <<() একই প্রভাব ফেলছে, তাই না?
solfish

@solfish: না exacllty: firse যেখানেই থাকুন না কেন একটি ফাইল বলে আশা করা হচ্ছে ব্যবহার করা যেতে পারে, দ্বিতীয় যে ফাইলের নাম জন্য একটি ইনপুট ফেরৎ হয়
enzotib

23

প্রক্রিয়া প্রতিস্থাপনের সাথে এখানে আপনি তিনটি জিনিস করতে পারেন যা অন্যথায় অসম্ভব।

একাধিক প্রক্রিয়া ইনপুট

diff <(cd /foo/bar/; ls) <(cd /foo/baz; ls)

পাইপ দিয়ে এটি করার সহজ উপায় নেই।

এসটিডিন সংরক্ষণ করা হচ্ছে

বলুন আপনার নিম্নলিখিত রয়েছে:

curl -o - http://example.com/script.sh
   #/bin/bash
   read LINE
   echo "You said ${LINE}!"

এবং আপনি এটি সরাসরি চালাতে চান। নিম্নলিখিতগুলি খারাপভাবে ব্যর্থ। স্ক্রিপ্টটি পড়তে বাশ ইতিমধ্যে STDIN ব্যবহার করছে, সুতরাং অন্যান্য ইনপুটটি অসম্ভব।

curl -o - http://example.com/script.sh | bash 

তবে এই উপায়টি পুরোপুরি কার্যকর হয়।

bash <(curl -o - http://example.com/script.sh)

আউটবাউন্ড প্রক্রিয়া প্রতিস্থাপন

এছাড়াও নোট করুন যে প্রক্রিয়া প্রতিস্থাপন অন্যভাবেও কাজ করে। সুতরাং আপনি এর মতো কিছু করতে পারেন:

(ls /proc/*/exe >/dev/null) 2> >(sed -n \
  '/Permission denied/ s/.*\(\/proc.*\):.*/\1/p' > denied.txt )

এটা একটা জটিল উদাহরণ একটি বিট, কিন্তু এটা পাঠায় stdout- এ থেকে /dev/null, যখন বংশীধ্বনিতুল্য দ্বারা stderr একটি sed স্ক্রিপ্ট ফাইল, যার জন্য "অনুমতি অস্বীকৃত" ত্রুটি দেখানো হয়, এবং তারপর একটি ফাইলে সেই ফলাফল পাঠায় নাম বের করে আনতে।

মনে রাখবেন যে প্রথম কমান্ড এবং stdout পুনঃনির্দেশটি বন্ধনী ( সাবશેল ) এ রয়েছে যাতে কেবল সেই আদেশের ফলাফলটি প্রেরণ হয় /dev/nullএবং এটি বাকী রেখার সাথে বিশৃঙ্খলা সৃষ্টি করে না।


উল্লেখ্য যে, এ মূল্য diffউদাহরণ আপনি যেখানে The যত্নশীল করতে চাইতে পারেন cdব্যর্থ হতে পারে: diff <(cd /foo/bar/ && ls) <(cd /foo/baz && ls)
পিএইচকে

" স্টেডার পাইপিংয়ের সময়": এই নলটি পাইপিং নয় , তবে একটি ফিফো ফাইল দিয়ে যাচ্ছেন?
গৌথির

@ গৌথির নং; কমান্ডটি ফিফো দিয়ে নয় বরং ফাইল বর্ণনাকারীর একটি রেফারেন্সের সাথে প্রতিস্থাপিত হয়। সুতরাং "প্রতিধ্বনি <(প্রতিধ্বনি)" এর "/ dev / fd / 63" এর মতো কিছু পাওয়া উচিত যা একটি বিশেষ চরিত্রের ডিভাইস যা এফডি নম্বর
63৩

10

যদি কোনও কমান্ড ফাইলগুলির একটি তালিকা আর্গুমেন্ট হিসাবে গ্রহণ করে এবং সেই ফাইলগুলি ইনপুট (বা আউটপুট, তবে সাধারণত হয় না) হিসাবে প্রক্রিয়া করে, তবে এই ফাইলগুলির প্রত্যেকটি প্রক্রিয়া সাবস্ক্রিপশন দ্বারা স্বচ্ছভাবে সরবরাহ করা নামযুক্ত পাইপ বা / dev / fd সিউডো-ফাইল হতে পারে:

$ sort -m <(command1) <(command2) <(command3)

এটি সাজানোর জন্য তিনটি কমান্ডের আউটপুট "পাইপ" করবে, কারণ সারণি কমান্ড লাইনে ইনপুট ফাইলগুলির একটি তালিকা নিতে পারে।


1
আইআইআরসি <(কমান্ড) সিনট্যাক্স কেবলমাত্র ব্যাশ বৈশিষ্ট্য।
ফিলোমাথ

@ ফিলোমাথ: এটি জেডএসএইচেও রয়েছে।
কালেব

ঠিক আছে, জেডএসএইচে সব কিছু রয়েছে ... (বা কমপক্ষে চেষ্টা করার চেষ্টা রয়েছে)।
ফিলোমাথ

@ ফিলোমথ: অন্যান্য শেলগুলিতে প্রক্রিয়া প্রতিস্থাপন কীভাবে প্রয়োগ করা হয়?
ক্যামহ

4
@ ফিলোমথ <(), অনেক উন্নত শেল বৈশিষ্ট্যের মতো, মূলত একটি ksh বৈশিষ্ট্য ছিল এবং এটি ব্যাশ এবং জেডএস দ্বারা গৃহীত হয়েছিল। psubবিশেষত একটি মাছের বৈশিষ্ট্য, পসিক্সের সাথে কিছুই করার নেই।
গিলস

3

এটি লক্ষ করা উচিত যে প্রক্রিয়া প্রতিস্থাপনটি ফর্মের মধ্যে সীমাবদ্ধ নয় <(command), যা commandফাইল হিসাবে আউটপুট ব্যবহার করে । এটি এমন ফর্ম হতে পারে >(command)যা কোনও ফাইলকেও ইনপুট হিসাবে ফিড করে command। @ এনজোটিবের উত্তরে বাশ ম্যানুয়ালের উদ্ধৃতিতে এটি উল্লেখ করা হয়েছে।

জন্য date | catউপরোক্ত উদাহরণে, একটি কমান্ড ফর্ম প্রক্রিয়া প্রতিকল্পন ব্যবহার করে >(command)অর্জন করা একই প্রভাব হবে,

date > >(cat)

নোট করুন যে >আগে >(cat)প্রয়োজনীয়। echo@ কালেবের উত্তর হিসাবে এটি আবার পরিষ্কারভাবে চিত্রিত করা যেতে পারে ।

$ echo >(cat)
/dev/fd/63

সুতরাং, অতিরিক্ত ছাড়া >, স্টাডারকে একটি বার্তা প্রিন্ট date >(cat)করার মতোই date /dev/fd/63হবে।

মনে করুন আপনার কাছে এমন একটি প্রোগ্রাম রয়েছে যা কেবলমাত্র পরামিতি হিসাবে ফাইলের নাম নেয় এবং প্রক্রিয়া করে না stdinবা stdout। এটি psub.shচিত্রিত করার জন্য আমি ওভারসিম্প্লিফাইড স্ক্রিপ্টটি ব্যবহার করব । বিষয়বস্তু psub.shহয়

#!/bin/bash
[ -e "$1" -a -e "$2" ] && awk '{print $1}' "$1" > "$2"

মূলত, এটা পরীক্ষা যে তার আর্গুমেন্ট উভয় ফাইল (অগত্যা নিয়মিত না ফাইল) এবং এই ক্ষেত্রে যদি, প্রতিটি লাইনের প্রথম ক্ষেত্রের লিখতে "$1"করার "$2"awk ব্যবহার করে। তারপরে, একটি কমান্ড যা এ পর্যন্ত উল্লেখ করা সমস্ত সংযুক্ত করে,

./psub.sh <(printf "a a\nc c\nb b") >(sort)

এটি মুদ্রণ করবে

a
b
c

এবং এর সমতুল্য

printf "a a\nc c\nb b" | awk '{print $1}' | sort

তবে নিম্নলিখিতগুলি কাজ করবে না এবং আমাদের এখানে প্রক্রিয়া বিকল্প ব্যবহার করতে হবে,

printf "a a\nc c\nb b" | ./psub.sh | sort

বা এর সমতুল্য ফর্ম

printf "a a\nc c\nb b" | ./psub.sh /dev/stdin /dev/stdout | sort

যদি উপরে বর্ণিত বিষয়গুলি ছাড়াও যদি ./psub.shএটিও পড়ে থাকে stdinতবে এ জাতীয় সমতুল্য ফর্মটি বিদ্যমান নেই এবং সেই ক্ষেত্রে প্রক্রিয়া প্রতিস্থাপনের পরিবর্তে আমরা ব্যবহার করতে পারি এমন কিছুই নেই (অবশ্যই আপনি একটি নামী পাইপ বা টেম্প ফাইলও ব্যবহার করতে পারেন, তবে এটি অন্যটি গল্প).

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.