বাশ পাইপলাইনগুলিতে `হ্যাঁ ব্যবহার করা * কেন * অসীম লুপের কারণ হয় না?


16

এর ডকুমেন্টেশন অনুসারে, কোনও পাইপলাইনে সমস্ত কমান্ড চালিয়ে যাওয়ার আগে শেষ না হওয়া পর্যন্ত বাশ অপেক্ষা করে

শেলটি পাইপলাইনে সমস্ত কমান্ডের জন্য একটি মান ফেরত দেওয়ার আগে শেষ হওয়ার জন্য অপেক্ষা করে।

তাহলে কমান্ডটি ততক্ষনে yes | trueসমাপ্ত হবে কেন ? না করা উচিত yesলুপ সময় প্রবেশ করুন এবং পাইপলাইন কারণ কখনোই ফিরে আসতে?


আর subquestion: অনুযায়ী POSIX বৈশিষ্ট , শেল পাইপলাইনগুলি গত কমান্ড শেষ বা অপেক্ষার সব কমান্ড শেষ হওয়া পর্যন্ত পারেন আগমন চয়ন করতে পারেন। সাধারণ শাঁসগুলি কি এই অর্থে আলাদা আচরণ করে? এমন কোন শাঁস আছে যেখানে yes | trueচিরকালের জন্য লুপ থাকবে?


yes | tee >(true) >/dev/nullবিটিডব্লিউ, যেমনটি আপনি প্রত্যাশা করেছিলেন teeতেমনই trueকরবে , যতক্ষণ না সমস্ত লেখক মারা যায়, সুতরাং প্রস্থান করা এটিকে পুরোপুরি ব্যহত করবে না।
চার্লস ডাফি

1
trueমূলত একটি {return 0;}প্রোগ্রাম, তাই আমি এটি দীর্ঘকাল ধরে চলতে আশা করি না, চিরতরে ছেড়ে দিন।
দিমিত্রি গ্রিগরিয়েভ

উত্তর:


33

যখন trueপ্রস্থান করে, পাইপের পঠিত পাশ বন্ধ করা হয়, কিন্তু yesলেখার পাশ থেকে লিখতে চেষ্টা করার চলতে থাকে। এই অবস্থাকে "ভাঙা পাইপ" বলা হয় এবং এটি কার্নেলকে SIGPIPEসংকেত প্রেরণ করে yes। যেহেতু yesএই সংকেতটি সম্পর্কে বিশেষ কিছু নেই, তাই এটি হত্যা করা হবে। যদি এটি সিগন্যালটিকে উপেক্ষা করে তবে এর writeকলটি ত্রুটি কোড সহ ব্যর্থ হবে EPIPE। যে প্রোগ্রামগুলি সেগুলি লক্ষ্য করা EPIPEএবং লেখা বন্ধ করার জন্য প্রস্তুত থাকতে হবে বা তারা অসীম লুপে যাবে।

আপনি যদি strace yes | true1 করেন তবে কার্নেলটি উভয় সম্ভাবনার জন্য প্রস্তুত করতে দেখতে পাবেন:

write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 4096) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=17556, si_uid=1000} ---
+++ killed by SIGPIPE +++

straceডিবাগার এপিআইয়ের মাধ্যমে ইভেন্টগুলি পর্যবেক্ষণ করছে, যা প্রথমে এটি ত্রুটির সাথে ফিরে আসা সিস্টেম কল এবং তারপরে সংকেত সম্পর্কে বলে। থেকে yesএর দৃষ্টিকোণ, যদিও, সংকেত প্রথম ঘটবে। (প্রযুক্তিগতভাবে, কার্নেলটি ব্যবহারকারীর স্থানে নিয়ন্ত্রণ ফিরে পাওয়ার পরে সংকেত সরবরাহ করা হয়, তবে আরও কোনও মেশিনের নির্দেশাবলী কার্যকর করার আগে, সুতরাং writeসি লাইব্রেরিতে "র‌্যাপার" ফাংশনটি সেট errnoকরে অ্যাপ্লিকেশনটিতে ফিরে আসার সুযোগ পায় না ।)


1 দুঃখের বিষয়, straceলিনাক্স-নির্দিষ্ট। বেশিরভাগ আধুনিক ইউনিক্সে কিছু কমান্ড থাকে যা একই রকম কিছু করে, তবে এটির প্রায়শই আলাদা নাম থাকে এটি সম্ভবত সিস্কল আর্গুমেন্টগুলি পুরোপুরি ডিকোড করে না এবং কখনও কখনও এটি কেবল মূলের জন্যই কাজ করে।


3
@ হুগমগ সেক্ষেত্রে পাইপটি সম্পূর্ণ অপ্রাসঙ্গিক।
মারু

3
@ হুগমগ কারণ কোনও কিছুই yesপাইপের সাথে সংযুক্ত নেই ।
মুড়ু

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

2
@ হুগমগ, এটি একইভাবে yes >/dev/nullচিরকালের জন্য লুপ করে চলেছে যা চিরকালের জন্য লুপ করে চলেছে । এটি পাইপলাইনগুলি সম্পর্কে কিছুই প্রদর্শন করে না যা সাধারণ কমান্ডগুলির ক্ষেত্রেও সত্য নয় (টম-পয়েন্ট-অব সমাপ্তির আচরণ যেমন টম পয়েন্টটি সরল কমান্ডের ক্ষেত্রেও সত্য)।
চার্লস ডাফি

2
@ জওয়োল: আমি মনে করি আমরা আমাদের পদগুলি এখানে কিছুটা পৃথক অর্থ সহ ব্যবহার করছি, বা কিছুটা ভিন্ন দৃষ্টিকোণ থেকে জিনিসগুলি নিয়ে ভাবছি ... তবে উভয় ক্ষেত্রেই write()(লিবিসি-তে ফাংশন) ফিরে আসে না (এটি অনুসরণকারী পিসিতে স্থানান্তর নিয়ন্ত্রণ) পরে না আসে সিগন্যাল হ্যান্ডলারটি চালিত হয়েছে, তবে যেহেতু সিগন্যাল হ্যান্ডলার প্রোগ্রামটি শেষ করে, নিয়ন্ত্রণ কখনই স্থানান্তরিত হয় write()না এবং তাই কখনই ফিরে আসে না। হ্যাঁ, কিছু xxx_write()ফাংশন রিটার্ন থাকার পরে এটি কার্নেলে প্রয়োগ করা হয়েছে -EPIPE, তবে আমরা একটি ব্যবহারকারী-স্থান প্রোগ্রাম ডিবাগ করছি এবং এতে আগ্রহী নই।
ডায়েটারিচ এপ্প

5

হ্যাঁ এমন কোনও শাঁস আছে কি না | সত্য চিরতরে লুপ?

অসম্ভব, যেহেতু yesকমান্ডটি পাইপটি ব্যবহার করছে এবং পাইপটি নষ্ট হয়ে গেলে এটি ব্যর্থ হবে। sleepঅন্যদিকে, পাইপটি ব্যবহার করে না, তাই:

sleep 100000000 | true

কমপক্ষে 100000000 সেকেন্ডের জন্য চলবে।


2
সমস্ত আধুনিক শেলগুলি সম্পর্কে সতর্কতা অবলম্বন করুন যা কোনও পাইপে সর্বশেষ (ডানদিকে) বিল্টিন কমান্ডের জন্য কাঁটাচামচ করে না এবং যেখানে trueকোনও বিল্টিন রয়েছে। এই সাম্প্রতিক সংস্করণ প্রযোজ্য Bourne Shell, ksh93, zsh। আপনি যদি ^Zএইরকম একটি কমান্ড চলমান অবস্থায় আঘাত করেন তবে এটি ঘুম স্থগিত করবে এবং বহিরাগত সাহায্য ছাড়া শেলটি কখনই পুনরুদ্ধার করতে সক্ষম হবে না।
স্কিলি

3
zsh 4.3.4 (i386-pc-solaris2.11) এখানে, সুতরাং দেখে মনে হচ্ছে এটি সম্প্রতি পরিবর্তিত হয়েছিল। আকর্ষণীয় ধারণা, আমি বোর্ন শেলের জন্য একই ধরণের ফিক্স বাস্তবায়ন করতে পারি কিনা তা আমার একবার দেখার প্রয়োজন। এটি কীভাবে কাজ করে তা এখনও একটি প্রশ্ন রয়েছে এবং বোর্ন শেলের মতো কোন টিটিটি প্রক্রিয়া গ্রুপটি ব্যবহৃত হয়েছে যে সত্য যে সর্বাধিক কমান্ডটি একটি অন্তর্নির্মিত তা ঘুমের জন্য প্রক্রিয়া গ্রুপটি ইতিমধ্যে স্থাপনের পরে আবিষ্কার করা হয়েছিল।
স্কিলি

2
আমি যা বুঝি তার থেকে চার্লেস ডফি শালিকভাবে শ এর একটি সংস্করণ বজায় রাখেন, যেখানে তিনি আধুনিক শেল থেকে উন্নতিগুলি ব্যাকপোর্ট করেন। তিনি এ সম্পর্কে এখানে কোথাও পোস্ট করেছেন।
মুরু

3
উত্তরাধিকারী সংরক্ষণাগারগুলিতে বোর্ন শেল ২০০ until সাল পর্যন্ত বজায় রাখা হয়েছিল তবে এখনও পুরোপুরি পোর্টেবল করা হয়নি কারণ এতে এখনও কল রয়েছে sbrk()। একটি পোর্টেবল এবং রক্ষণাবেক্ষণযোগ্য সংস্করণটি চতুর সরঞ্জাম বান্ডলে রয়েছে এবং @ চার্লস ডাফি ইতিমধ্যে তথ্যের জন্য একটি অবস্থান আবিষ্কার করেছেন ;-)
সহজেই

2
@ বোর্ন শেলকে আমি যে বৈশিষ্ট্যগুলি ব্যাকপোর্ট করেছি, তার অনেকগুলি আমার থেকে bsh(ভিবিআরটোস থেকে বার্থল্ড শেল, ইউএনওএসের ভার্চুয়াল মেমরির উন্নত সংস্করণ - প্রথম ইউএনএক্স ক্লোন)। Bsh 1984 এবং 1985 সালে অনেক csh বৈশিষ্ট্য পেয়েছিল তবে ইউএনওএসের উরফ মেকানিজম 1980 এর আগে সিএসএসের চেয়ে সেরা ছিল। অন্য নতুন বোর্ন শেল বৈশিষ্ট্যগুলি পসিক্স থেকে এসেছে যাতে এটি পসিক্স সম্মতিতে যেতে পারে।
স্কিলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.