লিনাক্সে "ফুটো" পাইপ


12

ধরে নেওয়া যাক আপনার নীচের মতো পাইপলাইন রয়েছে:

$ a | b

যদি bস্টিডিন প্রসেসিং বন্ধ করে দেয়, কিছুক্ষণ পরে পাইপটি ভরে যায় এবং লেখার পরে aতার স্টাডাউট অবধি ব্লক হয়ে যায় (হয় না bআবার প্রক্রিয়াজাতকরণ শুরু হয় না মারা যায়)।

যদি আমি এটি এড়াতে চাইতাম তবে আমি এর চেয়ে বড় পাইপ (বা আরও সহজভাবে buffer(1)) ব্যবহার করতে প্ররোচিত হতে পারি :

$ a | buffer | b

এটি কেবল আমাকে আরও সময় কিনে ফেলবে, তবে শেষ aপর্যন্ত থামবে।

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

এটির সংক্ষেপে আমি একটি আবদ্ধ, ফুটো বাফারের মতো কিছু পেতে চাই:

$ a | leakybuffer | b

আমি সম্ভবত এটি সহজেই কোনও ভাষায় প্রয়োগ করতে পারি, আমি কেবল ভাবছিলাম যে "ব্যবহারের জন্য প্রস্তুত" (বা ব্যাশ ওয়ান-লাইনারের মতো কিছু) আমি অনুপস্থিত রয়েছি কিনা।

দ্রষ্টব্য: উদাহরণগুলিতে আমি নিয়মিত পাইপ ব্যবহার করছি তবে নামটি পাইপগুলিতে প্রশ্নটি সমানভাবে প্রযোজ্য


আমি নীচের উত্তরটি প্রদান করার সময়, আমি লিকব্যুফার কমান্ডটি বাস্তবায়নেরও সিদ্ধান্ত নিয়েছি কারণ নীচের সহজ সমাধানটির কিছু সীমাবদ্ধতা ছিল: https://github.com/CAFxX/leakybuffer


নামকরণ পাইপ কি সত্যিই পূরণ করে? আমি ভাবতাম নামক পাইপগুলি এর সমাধান, তবে আমি নিশ্চিত করে বলতে পারি না।
ওয়াইল্ডকার্ড

3
নামী পাইপগুলিতে (ডিফল্টরূপে) নামবিহীন পাইপগুলির সমান ক্ষমতা রয়েছে,
এএফএআইকি

উত্তর:


14

সবচেয়ে সহজ উপায় হ'ল কিছু প্রোগ্রামের মাধ্যমে পাইপ দেওয়া যা ননব্লকিং আউটপুট সেট করে। এখানে সরল পার্ল অনেলাইনার (যা আপনি লিকেবফার হিসাবে সংরক্ষণ করতে পারেন ) যা এটি করে:

সুতরাং আপনার a | bহয়ে:

a | perl -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | b

যা হয় তা হ'ল ইনপুট পড়ুন এবং আউটপুট (একই হিসাবে cat(1)) লিখুন তবে আউটপুটটি ব্লক করা হচ্ছে - এর অর্থ যদি লেখায় ব্যর্থ হয় তবে এটি ত্রুটি ফিরে পাবে এবং ডেটা হারাবে, তবে প্রক্রিয়াটি ইনপুটটির পরবর্তী লাইনে চলতে থাকবে কারণ আমরা সুবিধামত উপেক্ষা করব ত্রুটি. আপনি যেমন চান তেমন প্রক্রিয়াটি এক প্রকারের লাইন-বাফার, তবে নীচে সতর্কীকরণ দেখুন।

উদাহরণস্বরূপ আপনি পরীক্ষা করতে পারেন:

seq 1 500000 | perl -w -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { print }' | \
    while read a; do echo $a; done > output

আপনি outputহারিয়ে যাওয়া রেখাগুলি (সঠিক আউটপুট আপনার শেল এর গতির উপর নির্ভর করে ইত্যাদি) এর সাথে ফাইল পাবেন :

12768
12769
12770
12771
12772
12773
127775610
75611
75612
75613

আপনি দেখতে পেলেন যে শেলের পরে লাইনগুলি হারিয়েছে 12773, তবে একটি অসঙ্গতিও - পার্লটির পক্ষে যথেষ্ট পরিমাণে বাফার ছিল না 12774\nতবে 1277এটি কেবল এটি লিখেছিল - এবং পরবর্তী সংখ্যাটি 75610লাইনের শুরুতে শুরু হয় না, এটি সামান্য করে তোলে কুশ্রী।

লেখাগুলি সম্পূর্ণরূপে সফল না হলে পার্ল শনাক্ত করার মাধ্যমে এটি উন্নত হতে পারে এবং তারপরে পরবর্তী সময়ে নতুন লাইনগুলি উপেক্ষা করার সময় লাইনের অবশিষ্ট অংশটি ফ্লাশ করার চেষ্টা করুন, তবে এটি পার্ল স্ক্রিপ্টকে আরও জটিল করে তুলবে, সুতরাং এটি অনুশীলন হিসাবে রেখে গেছে আগ্রহী পাঠক :)

আপডেট (বাইনারি ফাইলগুলির জন্য): আপনি যদি নতুন লাইন টার্মিনেটেড লাইনগুলি (লগ ফাইল বা অনুরূপ) প্রসেস না করে থাকেন তবে আপনার কমান্ডটি সামান্য পরিবর্তন করা দরকার, বা পার্ল আপনার প্রচুর পরিমাণে মেমরি গ্রহণ করবে (আপনার ইনপুটটিতে কতবার নতুন লাইন অক্ষর প্রদর্শিত হবে তার উপর নির্ভর করে):

perl -w -MFcntl -e 'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (read STDIN, $_, 4096) { print }' 

এটি বাইনারি ফাইলগুলির জন্যও সঠিকভাবে কাজ করবে (অতিরিক্ত মেমরি না খেয়ে)।

আপডেট 2 - সুন্দর টেক্সট ফাইল আউটপুট: আউটপুট বাফারগুলি এড়ানো ( syswriteপরিবর্তে print):

seq 1 500000 | perl -w -MFcntl -e \
    'fcntl STDOUT,F_SETFL,O_NONBLOCK; while (<STDIN>) { syswrite STDOUT,$_ }' | \
    while read a; do echo $a; done > output

আমার জন্য "মার্জড লাইনগুলি" নিয়ে সমস্যাগুলি ঠিক করেছে বলে মনে হচ্ছে:

12766
12767
12768
16384
16385
16386

(দ্রষ্টব্য: কোনটি লাইন আউটপুট কেটে কেটেছিল তা যাচাই করতে পারে: perl -ne '$c++; next if $c==$_; print "$c $_"; $c=$_' outputঅনেলাইনার)


আমি অনলাইনারকে ভালবাসি: আমি কোনও পার্ল বিশেষজ্ঞ নই, যদি কেউ উপরে বর্ণিত উন্নতির পরামর্শ দিতে পারে তবে তা দুর্দান্ত হবে
সিএএফএক্সএক্সএক্স

1
এটি কিছুটা কাজ বলে মনে হচ্ছে । তবে আমি যেভাবে আমার কমান্ডটি দেখছি perl -w -MFcntl -e 'fcntl STDOUT,F_SETFL,O_WRONLY|O_NONBLOCK; while (<STDIN>) { print }' | aplay -t raw -f dat --buffer-size=16000, পার্ল এটি OOM পরিচালকের দ্বারা নিহত হওয়া অবধি নিয়মিতভাবে আরও মেমরি বরাদ্দ করে।
পোনকডুডল

@ ওয়ালাকোলু যে বিষয়টি দেখানোর জন্য ধন্যবাদ, আমার মামলা লগ ফাইলগুলি স্ট্রিম করছে ... বাইনারি ফাইলগুলি সমর্থন করার জন্য সামান্য পরিবর্তনের জন্য আপডেট উত্তর দেখুন।
মাতিজা নালিস

জিএনইউ'র ddএস dd oflag=nonblock status=none
স্টাফেন চেজেলাস

1
দুঃখিত, আমার আবার খারাপ, পিআইপি-বিইউএফ বাইটের চেয়ে কম লিখেছে (লিনাক্সে 4096 কমপক্ষে পসিক্স দ্বারা কমপক্ষে 512 হওয়া আবশ্যক) তাই গৌণ গ্যারান্টিযুক্ত, সুতরাং $| = 1আপনার syswrite()পন্থা সংক্ষিপ্ত লেখাগুলি রোধ করতে পারে যতক্ষণ না লাইনগুলি যথাযথভাবে সংক্ষিপ্ত থাকে।
স্টাফেন চেজেলাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.