به نام خدا
در لینوکس دستگاه های مجازی زیادی وجود دارند که هر کدام برای کاری ساخته شده اند. وقتی برنامه ای در لینوکس اجرا میشود، می تواند از این دستگاه ها مثل دستگاه واقعی استفاده کند؛ از آنها اطلاعات دریافت کند و یا اطلاعاتی برای آنها ارسال کند. این دستگاه های مجازی را سیستم عامل میسازد و اصلا ربطی به سختافزار ندارند.
در آدرس /dev/ در لینوکس، دستگاه های مجازی و حقیقی قابل مشاهده هستند.
دستگاه مجازی null موجود در آدرس dev/null/ یکی از این دستگاه هاست. این دستگاه مجازی واقعا جالب است! بر خلاف اکثر دستگاه های مجازی، این فایل برای خواندن اطلاعات توسط برنامه ها استفاده نمی شود؛ بلکه کاربر یا برنامه ها فقط توانایی نوشتن در این فایل را دارند. هر چیزی که در این فایل نوشته شود، محو میشود و به هیچ تبدیل میشود! به همین دلیل من این فایل یا دستگاه مجازی را به سیاهچاله تشبیه می کنم.
شاید بگویید این فایل به چه درد می خورد؟ سوال خوبی است. در ادامه متن در این باره صحبت خواهیم کرد.
پیشنیاز ها
در این مطلب ما از مفاهیم stdout و stderr صحبت می کنیم. بهتر است در این زمینه ها اطلاعاتی داشته باشید ولی خیلی هم ضروری نیست.
هر زمانی دستوری در ترمینال لینوکس اجرا میشود، دو نوع خروجی ساخته میشود: خروجی عادی (stdout) و ارور (stderr). بطور پیشفرض هر دو خروجی در ترمینال نمایش داده میشوند.
برای مثال دستور زیر عبارت Hello world موجود در بین "" را در ترمینال نمایش میدهد. این خروجی در دسته stdout قرار دارد:
"echo "Hello world
دستور بعدی، کد وضعیت (Status code) اجرای دستور قبل را نمایش می دهد:
?$ echo
به دلیل اینکه دستور قبلی به طور کامل و موفقیت آمیز اجرا شد، خروجی دستور بالا ۰ است. در غیر این صورت، این کد متفاوت خواهد بود. ببینید که چه اتفاقی خواهد افتاد اگر دستوری غیرمتعارف وارد کنید؟
file descriptor
در اکوسیستم یونیکس، عدد ۱ برای stdout و ۲ برای stderr تعیین شده است. با استفاده از این اعداد می توانیم خروجی را به یک فایل هدایت کنیم.
نخست، ما خروجی stdout دستور echo را به یک فایل تکست (txt) هدایت می کنیم. در دستور زیر، ما نوع خروجی که می خواهیم هدایت شود (stdout) را مشخص نمی کنیم زیرا Bash به طور پیشفرض، stdout (عدد ۱) را هدایت می کند:
echo “Hello World” > log.txt
دستور زیر، stderr تولید شده توسط دستور را به فایل err.txt هدایت می کند:
استفاده از dev/null/
هدایت کردن خروجی به dev/null/
الآن برای یادگیری استفاده از dev/null/ آماده هستیم. اول بگذارید ببینیم که چگونه باید خروجی های stderr و stdout را از هم جدا کنیم. در دستور زیر، grep سعی می کند تا یک رشته را در دایرکتوری sys/ جست و جو کند:
grep -r hello /sys
اگر این دستور را بدون دسترسی روت اجرا کنیم، ارور بسیار زیادی تولید می کند؛ grep نمی تواند به تعدادی از فایل ها دسترسی داشته باشد. در چنین شرایطی، ارور "Permission denied" تولید می شود. الآن به کمک هدایت کردن، می توانیم به خروجی تمیزتری دست پیدا کنیم:
grep -r hello /sys/ 2> /dev/null
خروجی بالا خیلی بهتر است؛ نه؟ در خروجی کد بالا چیزی نمی بینیم چون تمام خروجی های stderr (شماره ۲) را با <2 به dev/null/ ارسال کردیم و به دلیل اینکه هیچ stdoutـی نداشتیم، چیزی نمایش داده نشد. اگر stdout وجود داشت، فقط آن نمایش داده میشد و stderr ها نمایش داده نمیشدند.
در مثال زیر میخواهیم پینگ برای سایت google.com را به دست آوریم:
ping google.com
الآن ما نمی خواهیم خروجی های موفق دستور را ببینیم. در نتیجه آنها را به dev/null/ منتقل می کنیم تا فقط stderr ها نمایش داده شوند:
ping google.com 1> /dev/null
هدایت کردن کل خروجی ها به dev/null/
برای هدایت کردن کل خروجی ها به dev/null/ می توانیم از دستور زیر استفاده کنیم:
grep -r hello /sys/ > /dev/null 2>&1
کد بالا خروجی /grep -r hello /sys را به dev/null/ هدایت می کند. ولی همانطور که قبلا اشاره شد، در صورت استفاده از <، فقط stdout هدایت میشود؛ به همین دلیل در بخش آخر دستور، گفتیم که file descriptor دو را به file discriptor یک هدایت کن. در نتیجه در خروجی ۱ (stdout)، stderr هم وجود خواهد داشت و دستور بالا، همه آنها را با هم به dev/null/ می فرستد.
چرا قبل از 1، علامت & قرار دادیم؟
این کار به این دلیل است که Bash متوجه شود منظور ما از ۱، فایلی با نام 1 نیست و منظور ما، file descriptor ۱ است.
اکنون به وضعیت اجرای دستور بالا توجه کنید:
میبینید که خروجی از نوع ۲ (stderr) است.
نکته: به جای کد بالا میتوانید از کد زیر استفاده کنید:
grep -r hello /sys/ &> /dev/null
عملگر <& کار ما را آسان کرده. این عملگر باعث میشود Bash متوجه شود که منظور ما، کل خروجی ها (اعم از ۱ و ۲) است و هر دو آنها را هدایت می کند.
امیدوارم از این مقاله راضی بوده باشید.
منبع متن: linuxhint.com