কেন রেসের শর্ত রয়েছে
পাইপের দুটি পক্ষই সমান্তরালভাবে কার্যকর হয়, একের পরের হয় না। এটি প্রদর্শনের জন্য খুব সহজ উপায় আছে: চালান
time sleep 1 | sleep 1
এটি এক নয়, দুটি নয়।
শেলটি দুটি শিশু প্রক্রিয়া শুরু করে এবং তাদের উভয়টি সম্পূর্ণ হওয়ার জন্য অপেক্ষা করে। এই দুই প্রক্রিয়ার সমান্তরাল চালানো যখন এটি শুধুমাত্র কারণে তাদের মধ্যে একজন অপরের সাথে সুসংগত হবে প্রয়োজন অপরের জন্য অপেক্ষা করতে। সিঙ্ক্রোনাইজেশনের সর্বাধিক সাধারণ বিষয় হ'ল ডান-হাতের ব্লকগুলি যখন তার স্ট্যান্ডার্ড ইনপুটটিতে ডেটা পড়ার জন্য অপেক্ষা করে এবং যখন বাম-হাত আরও ডেটা লেখেন তখন অবরুদ্ধ হয়ে যায়। কথোপকথনটিও ঘটতে পারে, যখন ডান হাতের তথ্য পড়তে ধীর হয় এবং তার লেখার অপারেশনটিতে বাম-হাতের ব্লকগুলি ডান-হাতটি আরও ডেটা না পড়া পর্যন্ত (পাইপটিতে নিজেই একটি বাফার থাকে, যার দ্বারা পরিচালিত হয়) কার্নেল, তবে এটির আকারটি একটি ছোট আকারের)।
সিঙ্ক্রোনাইজেশনের একটি বিন্দু পর্যবেক্ষণ করতে নিম্নলিখিত কমান্ডগুলি পর্যবেক্ষণ করুন ( sh -x
প্রতিটি কমান্ড এটি কার্যকরভাবে প্রিন্ট করে):
time sh -x -c '{ sleep 1; echo a; } | { cat; }'
time sh -x -c '{ echo a; sleep 1; } | { cat; }'
time sh -x -c '{ echo a; sleep 1; } | { sleep 1; cat; }'
time sh -x -c '{ sleep 2; echo a; } | { cat; sleep 1; }'
আপনি যা পর্যবেক্ষণ করছেন তাতে স্বাচ্ছন্দ্য না হওয়া অবধি পরিবর্তনের সাথে খেলুন।
যৌগিক কমান্ড দেওয়া হয়েছে
cat tmp | head -1 > tmp
বাম হাতের প্রক্রিয়াটি নিম্নলিখিতগুলি করে (আমি কেবলমাত্র আমার পদক্ষেপের সাথে সম্পর্কিত পদক্ষেপগুলি তালিকাভুক্ত করেছি):
cat
যুক্তি দিয়ে বাহ্যিক প্রোগ্রামটি কার্যকর করুন tmp
।
tmp
পড়ার জন্য উন্মুক্ত ।
- এটি ফাইলের শেষে পৌঁছায়নি, ফাইলটি থেকে একটি অংশ পড়ুন এবং এটি স্ট্যান্ডার্ড আউটপুটে লিখুন।
ডান হাতের প্রক্রিয়াটি নিম্নলিখিতগুলি করে:
tmp
প্রক্রিয়াতে ফাইল কেটে ফেলা, স্ট্যান্ডার্ড আউটপুট এ পুনঃনির্দেশ করুন ।
head
যুক্তি দিয়ে বাহ্যিক প্রোগ্রামটি কার্যকর করুন -1
।
- স্ট্যান্ডার্ড ইনপুট থেকে একটি লাইন পড়ুন এবং স্ট্যান্ডার্ড আউটপুট এ লিখুন।
সিঙ্ক্রোনাইজেশনের একমাত্র পয়েন্ট হ'ল ডান -3 বাম -3 এর জন্য একটি সম্পূর্ণ লাইন প্রক্রিয়াজাতকরণের জন্য অপেক্ষা করে। বাম -2 এবং ডান -1 এর মধ্যে কোনও সিঙ্ক্রোনাইজেশন নেই, সুতরাং এগুলি উভয় ক্রমেই ঘটতে পারে। তারা কী অর্ডারে ঘটবে তা অনুমানযোগ্য নয়: এটি সিপিইউ আর্কিটেকচার, শেল, কার্নেলের উপর নির্ভর করে, প্রসেসগুলি নির্ধারিত হওয়ার জন্য কোরের উপর নির্ভর করে, সেই সময়ের মধ্যে সিপিইউ কী বাধা দেয় ইত্যাদি উপর।
আচরণ কীভাবে পরিবর্তন করা যায়
সিস্টেম সেটিং পরিবর্তন করে আপনি আচরণটি পরিবর্তন করতে পারবেন না। কম্পিউটার আপনাকে যা করতে বলবে তা করে। আপনি এটিকে সমান্তরালভাবে ছাঁটাই tmp
এবং পড়তে বলেছেন tmp
, সুতরাং এটি দুটি জিনিসকে সমান্তরালে করে।
ঠিক আছে, এখানে একটি "সিস্টেম সেটিং" রয়েছে যা আপনি পরিবর্তন করতে পারেন: আপনি /bin/bash
কোনও আলাদা প্রোগ্রাম দ্বারা প্রতিস্থাপন করতে পারেন যা বাশ নয়। আমি আশা করি এটি বলার অপেক্ষা রাখে না যে এটি কোনও ভাল ধারণা নয়।
আপনি যদি পাইপটির বাম-হাতের আগে কাটা কাটাটি চান তবে আপনাকে এটি পাইপলাইনের বাইরে রাখা দরকার, উদাহরণস্বরূপ:
{ cat tmp | head -1; } >tmp
অথবা
( exec >tmp; cat tmp | head -1 )
যদিও আপনি এটি চান তা আমার কোনও ধারণা নেই। আপনি যে ফাইলটি খালি থাকতে জানেন তা পড়ার কী দরকার?
বিপরীতভাবে, আপনি যদি cat
পড়া শেষ করে আউটপুট পুনর্নির্দেশটি (ট্র্যাঙ্কেশন সহ) সংঘটিত হতে চান তবে আপনাকে অবশ্যই মেমরিতে ডেটা পুরোপুরি বাফার করতে হবে, যেমন
line=$(cat tmp | head -1)
printf %s "$line" >tmp
বা অন্য কোনও ফাইলে লিখুন এবং তারপরে এটি স্থানান্তরিত করুন। এটি সাধারণত স্ক্রিপ্টগুলিতে কাজ করার শক্তিশালী উপায় এবং এতে সুবিধা রয়েছে যে ফাইলটি মূল নামের মাধ্যমে দৃশ্যমান হওয়ার পূর্বে পুরো লেখা রয়েছে।
cat tmp | head -1 >new && mv new tmp
Moreutils সংগ্রহে একটি প্রোগ্রাম যা ঠিক যে, বলা আছে অন্তর্ভুক্ত sponge
।
cat tmp | head -1 | sponge tmp
কীভাবে সমস্যাটি স্বয়ংক্রিয়ভাবে সনাক্ত করা যায়
যদি আপনার লক্ষ্যটি ছিল খারাপভাবে লিখিত স্ক্রিপ্টগুলি নিয়ে যাওয়া এবং সেগুলি কোথায় যায় সেগুলি স্বয়ংক্রিয়ভাবে নির্ধারণ করা, তবে দুঃখিত, জীবনটি এত সহজ নয়। রানটাইম বিশ্লেষণ নির্ভরযোগ্যভাবে সমস্যাটি খুঁজে পাবে না কারণ cat
কাটা কাটা হওয়ার আগে কখনও কখনও পড়া শেষ করে। স্থির বিশ্লেষণ নীতিগতভাবে এটি করতে পারে; আপনার প্রশ্নের সরলীকৃত উদাহরণ শেলচেক দ্বারা ধরা পড়েছে , তবে এটি আরও জটিল স্ক্রিপ্টে অনুরূপ সমস্যাটি নাও পেতে পারে।