منبع اصلی نوشتار زیر در این لینک قرار دارد

پرسش و پاسخ شماره ۹


پرسش و پاسخ‌های رایج Bash  در Greg\'s Wiki

پرسش و پاسخ شماره ۹

میانگیری(buffering) چیست؟ یا، چرا این سطر فرمان من خروجی ندارد:

tail -f  logfile | grep \'foo bar\' | awk ...‎

اکثر فرمانهای استاندارد یونیکس وقتی به طور غیر محاوره‌ای به کارمی‌روند، خروجی را در حافظه میانجی قرار می‌دهند. بدین معنی که بلافاصله، هر کاراکتر(یا حتی هر سطر) را نمی‌نویسند، بلکه به جای آن، قبل از آنکه ابداً چیزی چاپ نمایند، تعداد زیادی از کاراکترها (اغلب 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

اگر این متعلق به یک برنامه کاربردی C خودتان است یا به کُد منبع آن دسترسی دارید، می‌توانید به این شکل میانگیری را غیرفعال کنید

setvbuf(stdout, 0, _IONBF, 0);

unbuffer

بسته expect یک برنامه unbuffer دارد که به طور مؤثری شگردی به برنامه‌های دیگر می‌زند که همیشه رفتاری داشته باشند چنانکه گویی به صورت محاوره‌ای به کار رفته‌اند(و اغلب میانگیری غیر فعال می‌شود). این هم یک مثال ساده:

tail -f logfile | unbuffer grep \'foo bar\' | awk ...

برنامه expect و unbuffer ابزارهای استاندارد POSIX نیستند، اما شاید از قبل در سیستم شما نصب شده باشند.

stdbuf

نگارشهای اخیر coreutils گنو (از 7.5 به این طرف)با یک برنامه سودمند دلپسند به نام stdbuf همراه می‌باشند، که می‌تواند در میان سایرین برای \"unbuffer\" نمودن خروجی استاندارد یک فرمان به کار برود. در اینجا کاربرد اساسی آن برای مثال ما آمده است:

tail -f logfile | stdbuf -oL grep \'foo bar\' | awk ...

در کُد فوق، ‎\"-oL\"‎ خروجی استاندارد را به طور سطری میانگیری می‌کند، حتی می‌توانید از ‎\"-o0\"‎ برای غیرفعال کردن کامل آن استفاده کنید. صفحات man و info دارای تمام جزئیات می‌باشند.

stdbuf ابزار استاندارد POSIX نیست، اماشاید از قبل در سیستم شما نصب شده باشد(اگر از توزیع‌های اخیر لینوکس استفاده می‌کنید،احتمالاً موجود خواهد بود).

less

اگر می‌خواهید به جای فیلتر کردن سطرهای انطباق نیافته، به سادگی عبارت مورد جستجو را متمایز(highlight) نمایید،می‌توانید در عوض فیلتر‎ tail -f‎ از برنامه less استفاده کنید:

$ less program.log
  • داخل less، با دستور \'/\' یک جستجو را شروع کنید(مشابه جستجو در vi). یا برنامه less را با گزینه ‎الگو ‎-p‎ شروع کنید.

  • این کار هر نمونه از عبارت جستجو را متمایز می‌کند.
  • حالا less را در وضعیت \"follow\" قرار بدهید، که به طور پیش‌فرض با ‎shift+f‎ به این وضعیت می‌رود.

  • قسمت انتهایی فایل تعیین شده را به طور فیلتر نشده، با متمایز شدن عبارت جستجو، دریافت خواهید نمود.

وضعیت \"follow\" با یک وقفه که احتمالاً در سیستم شما ‎ control+c‎ است، خاتمه می‌یابد. دستور \'/\' عبارت‌های منظم را قبول می‌کند، بنابراین شما می‌توانستید کارهایی مانند متمایز کردن تمام سطری که عبارت جستجو در آن ظاهر می‌شود را انجام دهید. برای جزئیات، ‎ man less‎ را کاوش نمایید.

coproc

اگر شما از پوسته ksh یا Bash نگارش 4.0+ استفاده می‌کنید، برای هر کاری که شما حقیقتاً تلاش می‌کنید با ‎ tail -f‎ انجام بدهید، کاربرد coproc و ‎fflush()‎ جهت ایجاد پردازش کمکی می‌تواند سودمند باشد. خوب توجه نمایید که coproc خودش میانگیری را بررسی نمی‌کند( در واقع مستعد مسائل میانگیری است -- از اینرو به fflush ارجاع می‌دهد). در اینجا فقط به coproc اشاره شد، به علت آنکه وقتی شخصی به طور پیوسته سعی در کنترل و عکس‌العمل نشان دادن به رشد آهسته فایل(یا لوله) می‌نماید، شاید بخواهد کاری کند که از کمک پردازشها سود خواهد برد.

مطالعه بیشتر


CategoryShell

پرسش و پاسخ 9 (آخرین ویرایش‎ 2012-09-14 07:43:13 ‎ توسط dslb-088-072-055-065)




به سیاره لینوکس امتیاز دهید

به اين صفحه امتياز دهيد