اکثر فرمانهای استاندارد یونیکس وقتی به طور غیر محاورهای به کارمیروند، خروجی را در حافظه میانجی قرار میدهند. بدین معنی که بلافاصله، هر کاراکتر(یا حتی هر سطر) را نمینویسند، بلکه به جای آن، قبل از آنکه ابداً چیزی چاپ نمایند، تعداد زیادی از کاراکترها (اغلب 4 کیلو بایت) را جمعآوری میکنند. در حالت فوق، فرمان grep خروجیاش را میانگیری میکند، و بنابراین awk ورودیاش را فقط در قطعات بزرگ دریافت میکند. میانگیری به طور عمدهای کارایی عملیات ورودی و خروجی را افزایش میدهد, و معمولاً به طریقی انجام میشود که تأثیر قابل رؤیت برای کاربر ندارد. دستور ساده tail -f از یک نشست ترمینال محاورهای به خوبی کار میکند، اما موقعی که دستور بخشی از یک خط لوله پیچیده باشد، شاید فرمان نتواند زمان واقعی(نزدیک) نیاز به خروجی نهایی را تشخیص بدهد. خوشبختانه، چند شگرد برای کنترل رفتار میانگیری ورودی-خروجی در دسترس میباشد.
مهمترین مطلب برای درک میانگیری آن است که نویسنده آنرا انجام میدهد، نه خواننده.
در این پرسش، ما لوله tail -f logfile | grep 'foo bar' | awk ... را داریم (با فرمان واقعی مشخص نشده AWK). اگر ما حقیقتاً tail -f logfile را اجرا نماییم، مشکلی وجود ندارد، به دلیل آنکه tail -f هرگز خروجیاش را بافر نمیکند. اگر tail -f logfile | grep 'foo bar' را به طور محاورهای اجرا کنیم نیز مشکلی وجود ندارد، زیرا grep نیز اگر خروجی استانداردش ترمینال باشد، خروجیاش را میانگیری نمیکند. گرچه، اگر خروجی grep به درون برنامه دیگری(ازقبیل یک فرمان AWK) لوله کشی بشود، برای بهبود کارایی، میانگیری را شروع میکند.
در این مثال عملی، برنامه grep واقعاً زائد است. ما میتوانیم آنرا حذف کنیم، و AWK را برای انجام عمل فیلتر کردن و هر چیز دیگری که انجام میدهد داشته باشیم:
tail -f logfile | awk '/foo bar/ ...'
در سایر موقعیتها، شاید این نوع یکپارچهسازی امکانپذیر نباشد. لیکن شما همواره اول باید سادهترین راه حل را جستجو نمایید.
برخی برنامههابه طور ویژهای گزینههای خاص خط فرمان را برای این قبیل مشکلات فراهم میکنند:
grep (به طور نمونه،گنو نگارش 2.5.1) |
--line-buffered |
sed (به عنوان مثال، گنو نگارش 4.0.6) |
-u,--unbuffered |
awk (برخی نگارشهای گنو) |
-W interactive, or use the fflush() function |
tcpdump و tethereal |
-l |
برای اجرای تمام خط لوله به طور بلادرنگ توسط هر فرمانی که در لوله مینویسد، باید بتوان به آن فرمان گفت که عمل میانگیری را غیر فعال کند. اگر آخرین فرمان خط لوله، در ترمینال مینویسد، به طور نوعی نیازی به ملاحظه خاصی نخواهد داشت.
اگر این متعلق به یک برنامه کاربردی C خودتان است یا به کُد منبع آن دسترسی دارید، میتوانید به این شکل میانگیری را غیرفعال کنید
setvbuf(stdout, 0, _IONBF, 0);
بسته expect یک برنامه unbuffer دارد که به طور مؤثری شگردی به برنامههای دیگر میزند که همیشه رفتاری داشته باشند چنانکه گویی به صورت محاورهای به کار رفتهاند(و اغلب میانگیری غیر فعال میشود). این هم یک مثال ساده:
tail -f logfile | unbuffer grep 'foo bar' | awk ...
برنامه expect و unbuffer ابزارهای استاندارد POSIX نیستند، اما شاید از قبل در سیستم شما نصب شده باشند.
نگارشهای اخیر coreutils گنو (از 7.5 به این طرف)با یک برنامه سودمند دلپسند به نام stdbuf همراه میباشند، که میتواند در میان سایرین برای "unbuffer" نمودن خروجی استاندارد یک فرمان به کار برود. در اینجا کاربرد اساسی آن برای مثال ما آمده است:
tail -f logfile | stdbuf -oL grep 'foo bar' | awk ...
در کُد فوق، "-oL" خروجی استاندارد را به طور سطری میانگیری میکند، حتی میتوانید از "-o0" برای غیرفعال کردن کامل آن استفاده کنید. صفحات man و info دارای تمام جزئیات میباشند.
stdbuf ابزار استاندارد POSIX نیست، اماشاید از قبل در سیستم شما نصب شده باشد(اگر از توزیعهای اخیر لینوکس استفاده میکنید،احتمالاً موجود خواهد بود).
اگر میخواهید به جای فیلتر کردن سطرهای انطباق نیافته، به سادگی عبارت مورد جستجو را متمایز(highlight) نمایید،میتوانید در عوض فیلتر tail -f از برنامه less استفاده کنید:
$ less program.log
داخل less، با دستور '/' یک جستجو را شروع کنید(مشابه جستجو در vi). یا برنامه less را با گزینه الگو -p شروع کنید.
حالا less را در وضعیت "follow" قرار بدهید، که به طور پیشفرض با shift+f به این وضعیت میرود.
وضعیت "follow" با یک وقفه که احتمالاً در سیستم شما control+c است، خاتمه مییابد. دستور '/' عبارتهای منظم را قبول میکند، بنابراین شما میتوانستید کارهایی مانند متمایز کردن تمام سطری که عبارت جستجو در آن ظاهر میشود را انجام دهید. برای جزئیات، man less را کاوش نمایید.
اگر شما از پوسته ksh یا Bash نگارش 4.0+ استفاده میکنید، برای هر کاری که شما حقیقتاً تلاش میکنید با tail -f انجام بدهید، کاربرد coproc و fflush() جهت ایجاد پردازش کمکی میتواند سودمند باشد. خوب توجه نمایید که coproc خودش میانگیری را بررسی نمیکند( در واقع مستعد مسائل میانگیری است -- از اینرو به fflush ارجاع میدهد). در اینجا فقط به coproc اشاره شد، به علت آنکه وقتی شخصی به طور پیوسته سعی در کنترل و عکسالعمل نشان دادن به رشد آهسته فایل(یا لوله) مینماید، شاید بخواهد کاری کند که از کمک پردازشها سود خواهد برد.
پرسش و پاسخ 9 (آخرین ویرایش 2012-09-14 07:43:13 توسط dslb-088-072-055-065)