পাইপ, কিভাবে পাইপলাইনে তথ্য প্রবাহিত হবে?


22

পাইপলাইনে কীভাবে ডেটা প্রবাহিত হবে তা আমি বুঝতে পারি না এবং আশা করি কেউ সেখানে কী চলছে তা স্পষ্ট করে বলতে পারে।

আমি ভেবেছিলাম কমান্ডগুলির একটি পাইপলাইন লাইন পদ্ধতিতে লাইনে ফাইলগুলি (টেক্সট, অ্যারেগুলি) প্রসেস করে। (যদি প্রতিটি কমান্ড নিজেই লাইন দিয়ে কাজ করে)

তবে মনে হয় এটি তেমন নয়।

এখানে একটি পরীক্ষার উদাহরণ দেওয়া হল। পাঠ্য কিছু লাইন আছে। আমি এগুলি বড়হাতে এবং প্রতিটি লাইন দু'বার পুনরাবৃত্তি করি। আমি এটা দিয়ে না cat text | tr '[:lower:]' '[:upper:]' | sed 'p'

প্রক্রিয়াটি অনুসরণ করতে আমরা এটিকে "ইন্টারেক্টিভলি" চালাতে পারি - ইনপুট ফাইলের নামটি এড়িয়ে যান cat। পাইপলাইনের প্রতিটি অংশ লাইন দিয়ে রেখা চালায়:

$ cat | tr '[:lower:]' '[:upper:]'
alkjsd
ALKJSD
sdkj
SDKJ
$ cat | sed 'p'
line1
line1
line1
line 2
line 2
line 2

তবে সম্পূর্ণ পাইপলাইনটি আমার সাথে ইনপুট শেষ করার জন্য অপেক্ষা করে EOFএবং তারপরেই ফলাফল মুদ্রণ করে:

$ cat | tr '[:lower:]' '[:upper:]' | sed 'p'
I am writing...
keep writing...
now ctrl-D
I AM WRITING...
I AM WRITING...
KEEP WRITING...
KEEP WRITING...
NOW CTRL-D
NOW CTRL-D

এটা কি তাই হওয়ার কথা? কেন এটি লাইন বাই লাইন নয়?


এটি পাইপ নয়, catস্টিডিন বন্ধ না হওয়া পর্যন্ত এটি বাফার করছে।
স্বর্ণিলোক

তবে trএবং sedcat
স্টিডিন

Stdio দ্বারা ব্যবহৃত ডিফল্ট (যা আমি বিশ্বাস করি উল্লিখিত সমস্ত প্রোগ্রাম ব্যবহার করে) হ'ল স্ট্ডার আনফার করা হয় না, এবং টার্মিনালে লেখার সময় স্টাডাউটটি লাইন বাফার হয় এবং অন্যথায় পুরোপুরি বাফার হয় (উদাহরণস্বরূপ যদি এটি কোনও ফাইল বা পাইপে লিখিত থাকে) । কিছু কমান্ডের পতাকা রয়েছে যা স্টাডআউট বাফারিংকে পরিবর্তন করতে পারে, তবে দেখে মনে হচ্ছে এটি তেমন নয়।
ক্যাস্পারড

উত্তর:


36

সি স্ট্যান্ডার্ড আই / ও লাইব্রেরি ( stdio) অনুসরণ করে একটি সাধারণ বাফারিং নিয়ম রয়েছে যা বেশিরভাগ ইউনিক্স প্রোগ্রাম ব্যবহার করে। যদি আউটপুট কোনও টার্মিনালে চলে যায় তবে প্রতিটি লাইনের শেষে এটি ফ্লাশ করা হয়; অন্যথায় এটি কেবল তখনই ফ্লাশ করা হয় যখন বাফার (আমার লিনাক্স / এমডি 64 সিস্টেমের মধ্যে 8 কে; আপনার নিজের চেয়ে আলাদা হতে পারে) পূর্ণ হয়।

আপনার সব ইউটিলিটি সাধারণ নিয়ম অনুসরণ করা হয়, তাহলে আপনি দেখতে হবে আউটপুট আপনার উদাহরণ সব বিলম্বিত ( cat|sed, cat|tr, এবং cat|tr|sed)। তবে এর ব্যতিক্রম আছে: জিএনইউ catকখনই এর আউটপুটটিকে বাফার করে না। এটি হয় না ব্যবহার করে stdioবা এটি ডিফল্ট stdioবাফারিং নীতি পরিবর্তন করে ।

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

সুতরাং যখনই আপনার catবাম দিকে পাইপ থাকবে, জিএনইউ সিস্টেমে, পাইপের মাধ্যমে ডেটা উত্তরণে বিলম্ব হবে না। catএমনকি পাতিপাতি যাচ্ছে না - আপনার টার্মিনাল যে করছে। যখন আপনি বিড়াল করুন না টাইপিং ইনপুট, আপনার টার্মিনাল "ক্যাননিকাল" মোডে রয়েছে - লাইন ভিত্তিক, সম্পাদনা ব্যাকস্পেস এবং Ctrl-ইউ মত কী সম্পাদনা করতে সুযোগ লাইন আপনার সাথে পাঠানোর আগে টাইপ করেছেন প্রস্তাব দিয়ে Enter

ইন cat|tr|sedউদাহরণস্বরূপ, trএখনও থেকে তথ্য গ্রহণ করা হয় catযত তাড়াতাড়ি আপনি টিপুন Enter, কিন্তু trঅনুসরণ করছে stdioডিফল্ট নীতি: তার আউটপুট একটি নল যাচ্ছে, তাই এটি প্রতিটি লাইনে পর ফ্লাশ না। এটি দ্বিতীয় পাইপটিতে লেখায় বাফারটি পূর্ণ হয়ে গেলে বা কোনও ইওএফ পাওয়ার পরে, যেটি প্রথমে আসে।

sedএছাড়াও stdioডিফল্ট নীতি অনুসরণ করে , তবে এর আউটপুটটি টার্মিনালে চলেছে তাই এটি প্রতিটি লাইনের সাথে এটি শেষ হওয়ার সাথে সাথেই এটি লিখবে। তাহলে - এই আপনি পাইপলাইন অপর প্রান্তের আপ কিছু শো সামনে কত টাইপ করতে হবে প্রভাব আছে sedছিল ব্লক-বাফার উপলব্ধ তার আউটপুট, আপনি অনেক (ভরাট হিসেবে দুইবার টাইপ করতে হবে চাই tr'র আউটপুট বাফার এবং sed গুলি আউটপুট' বাফার)।

গনুহ sedহয়েছে -uবিকল্প তাই যদি আপনি অর্ডার বিপরীত এবং ব্যবহৃত cat|sed -u|trআপনি আউটপুট সঙ্গে সঙ্গে আবার প্রদর্শিত দেখতে হবে। ( sed -uবিকল্পটি অন্য কোথাও উপলভ্য হতে পারে তবে আমার মনে হয় না এটি প্রাচীন ইউনিক্স likeতিহ্যের মতো cat -u) তবে আমি যতটা বলতে পারি এর সমতুল্য বিকল্প নেই tr

একটি ইউটিলিটি বলা হয় stdbufযা আপনাকে stdioডিফল্ট ব্যবহার করে এমন কোনও কমান্ডের বাফারিং মোড পরিবর্তন করতে দেয় । এটি কিছুটা নাজুক যেহেতু এটি LD_PRELOADসি লাইব্রেরিকে সমর্থন করার জন্য ডিজাইন করা হয়নি এমন কিছু অর্জন করতে ব্যবহার করে তবে এই ক্ষেত্রে এটি কাজ করে বলে মনে হয়:

cat | stdbuf -o 0 tr '[:lower:]' '[:upper:]' | sed 'p'

1
ধন্যবাদ! দুর্দান্ত উত্তর। সম্ভবত আমার কোনওভাবে প্রশ্নে বাফারিংয়ের উল্লেখ করা উচিত, যাতে এটি সন্ধান করতে পারে।
এক্সিলেটস

teeএবং ddসাধারণত তাদের নিজস্ব বিধি দ্বারা খেলুন। কল্পনাপ্রসূতভাবে সংযুক্ত হয়ে গেলে, তিনটি সরঞ্জাম stdbufব্যাকগ্রাউন্ড পাইপলাইনে কোনও প্রয়োজনের জন্য পোর্টেবলভাবে উপেক্ষা করতে পারে ।
মাইকসার্ভ

1
বিড়ালের অকেজো ব্যবহার এড়াতে এটি অন্যতম কারণ ।
hobbs

8

এটি আসলে আমাকে কিছুটা বুঝতে এবং আরও উত্তর দেওয়ার জন্য চিন্তাভাবনা করেছিল। দুর্দান্ত প্রশ্ন (আমি এটি পরবর্তী দিকে তুলে ধরব)

আপনি tr | sedউপরে আপনার ডিবাগিং আইটেম চেষ্টা করতে অবহেলা করেছেন :

>tr '[:lower:]' '[:upper:]' | sed 'p'
i am writing
still writing
now ctrl-d
I AM WRITING
I AM WRITING
STILL WRITING
STILL WRITING
NOW CTRL-D
NOW CTRL-D
>

সুতরাং স্পষ্টত trবাফারস। প্রতিদিন নতুন কিছু শিখুন!

সম্পাদনা :

আমি যেমন মনে করি, আমরা কারণটি বিচ্ছিন্ন করেছি, তবে কোনও ব্যাখ্যা সরবরাহ করি নি। আপনি যদি cat | trএটি অবিলম্বে লিখেন, আপনি যদি cat | sedতা অবিলম্বে লিখেন তবে আপনি যদি tr | sedএটির জন্য অপেক্ষা করেন EOF। আমি উত্তরটি তখন উত্স trবা sedউত্স কোডে সমাহিত করা এবং কোনও পাইপের সমস্যা নয় বলে পরামর্শ দেব ।

সম্পাদনা :

আমি দেখেছি যে আমি শেষ সম্পাদনাটি টাইপ করার সময় উম্পাস ব্যাখ্যাটি দিয়েছিল। ধন্যবাদ!


1
তারা বাফার! এবং উইম্পাসের যেমন উল্লেখ করা হয়েছে মোটামুটি 8 কেবি লাইনের সাথে পরীক্ষাটি দেখায় যে বাফারটি 8Kb প্রকৃতপক্ষে। চারপাশে কিছু খ্যাতি ভাগ করার জন্য আমি উভয় উত্তর গ্রহণ করতে চাই, তবে আমি উম্পাসকে আরও সম্পূর্ণ হিসাবে গ্রহণ করব। যাই হোক ধন্যবাদ!
এক্সিলিটস

1
কোনও সমস্যা নেই, আমার অভিজ্ঞতামূলক উত্তর ছিল, তাঁর জ্ঞান ছিল।
পোইসন অ্যারোহেড

এই প্রশ্নটিও দেখুন যা দেখায় যে কীভাবে কীভাবে ব্যবহার করা যায় stdbufতা সহায়ক হতে পারে। unix.stackexchange.com/questions/182537/…
জো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.