পেতে কয়েক উপায় আছে tail প্রস্থান করা:
দরিদ্র দৃষ্টিভঙ্গি: ফোর্স tail অন্য লাইন লিখতে
আপনি জোর করতে পারেন tail অবিলম্বে আউটপুট আরেকটি লাইন লিখতে grep একটি ম্যাচ পাওয়া গেছে এবং exited। এই কারণ হবে tail একটি পেতে SIGPIPE, এটি প্রস্থান করার কারণ। এটি করার একটি উপায় হল নজরদারি করা ফাইলটি সংশোধন করা tail পরে grep প্রস্থান করে।
এখানে কিছু উদাহরণ কোড রয়েছে:
tail -f logfile.log | grep -m 1 "Server Started" | { cat; echo >>logfile.log; }
এই উদাহরণে, cat পর্যন্ত প্রস্থান করা হবে না grep তার stdout বন্ধ হয়েছে, তাই tail আগে পাইপ লিখতে সক্ষম হতে পারে না grep তার stdin বন্ধ করার সুযোগ আছে। cat স্ট্যান্ডার্ড আউটপুট প্রচার করতে ব্যবহৃত হয় grep অপরিবর্তিত।
এই পদ্ধতির তুলনামূলকভাবে সহজ, কিন্তু বিভিন্ন downsides আছে:
- যদি
grep stdin বন্ধ করার আগে stdout বন্ধ, সবসময় একটি জাতি অবস্থা হতে হবে: grep stdout বন্ধ, triggering cat প্রস্থান করার জন্য, ট্রিগার echo, ট্রিগার tail একটি লাইন আউটপুট। এই লাইন পাঠানো হয় grep আগে grep stdin বন্ধ করার সুযোগ আছে, tail পাবেন না SIGPIPE এটি অন্য লাইন লিখে না হওয়া পর্যন্ত।
- এটি লগ ফাইল অ্যাক্সেস লিখতে হবে।
- আপনি লগ ফাইল সংশোধন সঙ্গে ঠিক আছে।
- আপনি যদি অন্য প্রক্রিয়া হিসাবে একই সময়ে লিখতে চান তবে আপনি লগ ফাইলটি দূষিত করতে পারেন (লেখার সাথে একত্রিত হতে পারে, একটি লগইন বার্তা মাঝখানে একটি নতুন লাইন দেখাতে পারে)।
- এই পদ্ধতির নির্দিষ্ট
tail এটা অন্যান্য প্রোগ্রামের সাথে কাজ করবে না।
- তৃতীয় পাইপলাইন পর্যায়টি দ্বিতীয় পাইপলাইনে পর্যায়টির রিটার্ন কোড অ্যাক্সেস করা কঠিন করে তোলে (যদি না আপনি একটি POSIX এক্সটেনশন ব্যবহার করেন যেমন
bash এর PIPESTATUS অ্যারে)। কারণ এই ক্ষেত্রে একটি বড় চুক্তি নয় grep সর্বদা 0 ফিরে আসবে, তবে সাধারণভাবে মাঝারি পর্যায়ে ভিন্ন কমান্ডের প্রতিস্থাপিত হতে পারে যার রিটার্ন কোডটি আপনি যত্নশীল (উদাহরণস্বরূপ, "সার্ভার শুরু হওয়া" সনাক্ত হওয়ার পরে 0 টি ফেরৎ এমন কিছু, 1 "সার্ভারটি শুরুতে ব্যর্থ হয়েছে" সনাক্ত করা হয়েছে) ।
পরবর্তী পন্থা এই সীমাবদ্ধতা এড়াতে।
একটি ভাল পদ্ধতি: পাইপলাইন এড়াতে
আপনি একসঙ্গে পাইপলাইন এড়াতে একটি ফিফো ব্যবহার করতে পারেন, একবার মৃত্যুদন্ড কার্যকর করার অনুমতি দেয় grep আয়। উদাহরণ স্বরূপ:
fifo=/tmp/tmpfifo.$$
mkfifo "${fifo}" || exit 1
tail -f logfile.log >${fifo} &
tailpid=$! # optional
grep -m 1 "Server Started" "${fifo}"
kill "${tailpid}" # optional
rm "${fifo}"
লাইন মন্তব্য সঙ্গে চিহ্নিত # optional মুছে ফেলা হতে পারে এবং প্রোগ্রাম এখনও কাজ করবে; tail এটি ইনপুট আরেকটি লাইন পড়তে না হওয়া পর্যন্ত বা কিছু অন্যান্য প্রক্রিয়া দ্বারা হত্যা করা হবে।
এই পদ্ধতির সুবিধাগুলি হল:
- আপনি লগ ফাইল সংশোধন করতে হবে না
- পদ্ধতির পাশাপাশি অন্যান্য ইউটিলিটি জন্য কাজ করে
tail
- এটি একটি জাতি অবস্থা থেকে ভোগ করে না
- আপনি সহজেই ফেরত মান পেতে পারেন
grep (অথবা আপনি ব্যবহার করছেন যে কোন বিকল্প কমান্ড)
এই পদ্ধতিতে নেতিবাচকতা জটিলতা, বিশেষ করে ফিফো পরিচালনা করা: আপনাকে নিরাপদভাবে একটি অস্থায়ী ফাইলের নাম তৈরি করতে হবে, এবং ব্যবহারকারীটি মাঝখানে Ctrl-C হিট করলেই অস্থায়ী ফিফো মুছে ফেলা হবে কিনা তা নিশ্চিত করতে হবে এই পান্ডুলিপি. এটি একটি ফাঁদ ব্যবহার করা যাবে।
বিকল্প পদ্ধতি: হত্যা করার জন্য একটি বার্তা পাঠান tail
আপনি পেতে পারেন tail পাইপলাইন স্তর এটি একটি সংকেত প্রেরণ করে প্রস্থান করার জন্য SIGTERM। চ্যালেঞ্জটি নির্ভরযোগ্যভাবে কোডে একই জিনিস দুটি জিনিস বুদ্ধিমান: tail এর পিআইডি এবং কিনা grep বহিষ্কৃত হয়েছে।
মত একটি পাইপলাইন সঙ্গে tail -f ... | grep ..., এটি সংরক্ষণ করার প্রথম পাইপলাইন মঞ্চ পরিবর্তন করা সহজ tail পিএইচডি ব্যাকগ্রাউন্ডিং দ্বারা একটি পরিবর্তনশীল tail এবং পড়া $!। এটি চালানোর দ্বিতীয় পাইপলাইন পর্যায়ে সংশোধন করা সহজ kill কখন grep প্রস্থান করে। সমস্যাটি হচ্ছে পাইপলাইনের দুটি স্তর পৃথক "নির্বাহ পরিবেশ" (পসিক্স স্ট্যান্ডার্ডের পরিভাষায়) মধ্যে চালানো হয় যাতে দ্বিতীয় পাইপলাইন স্তর প্রথম পাইপলাইন পর্যায়ে সেট করা কোনও ভেরিয়েবল পড়তে পারে না। শেল ভেরিয়েবলগুলি ব্যবহার না করেই, দ্বিতীয় পর্যায়টি অবশ্যই কোনভাবেই বের হওয়া উচিত tail এর পিআইডি যাতে এটি হত্যা করতে পারে tail কখন grep ফেরত, অথবা প্রথম পর্যায়ে কোনোভাবেই যখন অবহিত করা আবশ্যক grep আয়।
দ্বিতীয় পর্যায়ে ব্যবহার করতে পারে pgrep পেতে tail এর PID, কিন্তু এটি অবিশ্বাস্য (আপনি ভুল প্রক্রিয়াটি মিলতে পারে) এবং অ-পোর্টেবল ( pgrep POSIX মান দ্বারা নির্দিষ্ট করা হয় না)।
প্রথম পর্যায়ে পাইপের মাধ্যমে দ্বিতীয় পর্যায়ে পিআইডি পাঠাতে পারে echo PID ing, কিন্তু এই স্ট্রিং মিশ্রিত করা হবে tail এর আউটপুট। ডেমল্টিপ্লেক্সিংয়ের আউটপুটের উপর নির্ভর করে জটিল জটিল পালা স্কিম প্রয়োজন হতে পারে tail।
দ্বিতীয় পাইপলাইন পর্যায়ে প্রথম পাইপলাইন পর্যায়টি অবহিত করার জন্য আপনি একটি ফিফো ব্যবহার করতে পারেন grep প্রস্থান করে। তারপর প্রথম পর্যায়ে হত্যা করতে পারেন tail। এখানে কিছু উদাহরণ কোড রয়েছে:
fifo=/tmp/notifyfifo.$$
mkfifo "${fifo}" || exit 1
{
# run tail in the background so that the shell can
# kill tail when notified that grep has exited
tail -f logfile.log &
# remember tail's PID
tailpid=$!
# wait for notification that grep has exited
read foo <${fifo}
# grep has exited, time to go
kill "${tailpid}"
} | {
grep -m 1 "Server Started"
# notify the first pipeline stage that grep is done
echo >${fifo}
}
# clean up
rm "${fifo}"
এই পদ্ধতির পূর্বের পদ্ধতির সমস্ত পেশাদার এবং বিপর্যয় রয়েছে, এটি ব্যতীত জটিল।
Buffering সম্পর্কে একটি সতর্কতা
POSIX stdin এবং stdout স্ট্রিমগুলিকে পুরোপুরি buffered করার অনুমতি দেয়, যার মানে tail এর আউটপুট দ্বারা প্রক্রিয়া করা হতে পারে না grep একটি ইচ্ছাকৃতভাবে দীর্ঘ সময় জন্য। জিএনইউ সিস্টেমে কোন সমস্যা নেই: জিএনইউ grep ব্যবহারসমূহ read(), যা সব বাফার, এবং GNU এড়ানো tail -f নিয়মিত কল করে তোলে fflush() যখন stdout লেখা। অ-জিএনইউ সিস্টেমগুলি অক্ষম বা নিয়মিত ফ্লাশ বাফারের জন্য বিশেষ কিছু করতে পারে।