فصل ‎31‎- در مورد Zeroها و Nullها

 

Faultily faultless, icily regular, splendidly null

Dead perfection; no more.

--Alfred Lord Tennyson

‎/dev/zero‎‏ ... ‎/dev/null‎

استفاده‌های ‎/dev/null‎

‎/dev/null‎ را همچون یک سیاه‌چاله در نظر بگیرید. در اصل معادل یک فایل فقط نوشتنی است. هر چیز نوشته شده در آن ناپدید می‌گردد. تلاش برای خواندن یا خروجی گرفتن از آن بی نتیجه است. با وجود این، ‎/dev/null‎ هم در خط فرمان و هم در اسکریپت‌ها می‌تواند کاملاً سودمند باشد.

توقیف کردن stdout.

cat $filename >/dev/null
# محتویات فایل در خروجی استاندارد لیست نخواهد شد.

توقیف کردن stderr (از مثال ‎16-3‎).

rm $badname 2>/dev/null
#  پیغام خطاها ‎[stderr]‎ دور انداخته می‌شوند.

توقیف کردن هر دو خروجی stdout و stderr.

cat $filename 2>/dev/null >/dev/null
#        اگر ‎$filename‎ موجود نباشد، پیغام خطایی خارج نخواهد گردید.
# اگر ‎$filename‎ موجود باشد، محتویات فایل در ‎stdout‎ لیست نخواهد شد.
#             بنابراین، هیچ خروجی از سطر کد فوق حاصل نخواهد گردید.
#
#    این در موقعیت‌هایی که در آنها نیاز  است کد برگشتی یک فرمان تست
#+          بشود اما، خروجی فرمان مطلوب نیست، می‌تواند سودمند باشد.

#            به طوری که ‎Baris Cicek‎ اشاره می‌کند، این هم کار می‌کند:
#  cat $filename &>/dev/null

حذف کردن محتویات یک فایل، اما حفظ کردن خود فایل، با تمام مجوزهای همراه آن (از مثال ‎2-1‎ و مثال ‎2-3‎):

cat /dev/null > /var/log/messages
#  ‎: > /var/log/messages‎ دارای همان نتیجه است، اما پردازش جدیدی نیز تولید نمی‌کند.

cat /dev/null > /var/log/wtmp

خالی کردن محتویات یک فایل ثبت وقایع به طور خودکار (مخصوصاً مناسب برای برخورد با آن «کوکی‌های» نامطبوع ارسال شده به وسیله پایگاه‌های وب تجاری):

مثال ‎31-1‎. پنهان کردن ‎cookie jar‎

#                          مرورگر Netscape مهجور.
#       همین قاعده در مرورگرهای جدیدتر صدق می‌کند.

if [ -f ~/.netscape/cookies ]  #اگر هست، پاک شود.
then
  rm -f ~/.netscape/cookies
fi

ln -s /dev/null ~/.netscape/cookies
# اکنون تمام کوکی‌ها به جای ذخیره در دیسک، به یک سیاه‌چال فرستاده می‌شوند.

کاربردهای ‎/dev/zero‎

مانند ‎/dev/null‎، این ‎/dev/zero‎ نیز یک فایل شبه‌دستگاه است، اما در حقیقت جریانی از nullها (صفرهای باینری، نه از نوع ASCII) تولید می‌کند. خروجی نوشته شده در ‎/dev/zero‎ ناپدید می‌شود، و در حقیقت خواندن nullهای منتشر شده در آنجا تا اندازه‌ای دشوار است، اگر چه می‌تواند با od یا یک ویرایشگر هگز انجام بشود. استفاده عمده از ‎/dev/zero‎ در تولید یک فایل ساختگی با طول از پیش تعیین شده است، که به عنوان یک فایل swap موقتی در نظر گرفته شده باشد.

مثال ‎31-2‎. برقرار کردن یک فایل ‎swap‎ با استفاده از ‎/dev/zero‎

#!/bin/bash

# ایجاد یک فایل ‎swap‎

# یک فایل ‎swap‎، یک نهانگاه ذخیره موقت فراهم می‌کند
#+      که برخی عملیات سیستم فایل را سرعت می‌بخشد.

ROOT_UID=0         # ‎Root‎ دارای ‎$UID‎ برابر ‎0‎ است.
E_WRONG_USER=85    #                   ‎root‎ نیست؟

FILE=/swap
BLOCKSIZE=1024
MINBLOCKS=40
SUCCESS=0


#       این اسکریپت باید به عنوان ‎root‎ اجرا گردد.
if [ "$UID" -ne "$ROOT_UID" ]
then
  echo; echo "You must be root to run this script."; echo
  exit $E_WRONG_USER
fi  
  

blocks=${1:-$MINBLOCKS}          # تنظیم به پیش‌فرض ‎40‎ بلوک، اگر که
                                 #+ در خط فرمان مشخص نگردیده باشد.

# این سطر معادل با بلوک فرمان‌ پایین است.

# --------------------------------------------------
# if [ -n "$1" ]
# then
#   blocks=$1
# else
#   blocks=$MINBLOCKS
# fi
# --------------------------------------------------


if [ "$blocks" -lt $MINBLOCKS ]
then
  blocks=$MINBLOCKS              # دست کم باید ‎40‎ بلوک باشد.
fi  


#######################################################################
echo "Creating swap file of size $blocks blocks (KB)."
dd if=/dev/zero of=$FILE bs=$BLOCKSIZE count=$blocks  # فایل خروجی Zero
mkswap $FILE $blocks              #    برگزیدن آن به عنوان یک فایل ‎swap‎
swapon $FILE                      #                 فعال کردن فایل ‎swap‎
retcode=$?                        #                   همه چیز عملی شده؟
#                توجه کنید که اگر یک یا چند فرمان از این فرمان‌ها ناموفق
#+                      گردد، آنوقت می‌تواند باعث مشکلات ناخوشایندی بشود.
#######################################################################

#                  تمرین‌ها:
#  بلوک کد فوق را طوری بازنویسی کنید که
#       اگر به طور موفق اجرا نشد، آنوقت:

#  ‎(1‎ پیغام خطایی در stderr منعکس گردد,
#      ‎(2‎ تمام فایل‌های موقتی پاک بشوند، و
#      ‎(3‎ اسکریپت با یک روش مرتب با یک کد
#+               خطای متناسب خارج شود.

echo "Swap file created and activated."

exit $retcode

یک کاربرد دیگر ‎/dev/zero‎ برای تولید یک فایل zero با اندازه تخصیص یافته برای یک منظور خاص است، از قبیل سوار کردن یک سیستم فایل روی یک دستگاه loopback (مثال ‎17-8‎ را ببینید) یا حذف یک فایل «به طور امن» (مثال ‎16-61‎ را ببینید).

مثال ‎31-3‎. ایجاد یک ‎ramdisk‎

#!/bin/bash

# ramdisk.sh

#    یک ‎ramdisk‎ قطعه‌ای از حافظه RAM سیستم است و چنان
#+     عمل می‌کند که اگر یک سیستم فایل بود عمل می‌کرد.
#مزیت آن، دسترسی بسیار سریع (زمان خواندن-نوشتن) است.
#نواقص: بی‌ثبات بودن، از دست رفتن داده‌ها با ‎reboot‎ یا
#+        خاموشی سیستم، کاهش ‎RAM‎ در دسترس برای سیستم.
#
#                       مورد استفاده یک ‎ramdisk‎ چیست؟
#نگهداری مجموعه بزرگی از داده‌ها از قبیل یک جدول یا دیکشنری روی ‎ramdisk‎، جستجوی
#+ داده‌ها را سرعت می‌بخشد، چون دستیابی حافظه بسیار سریع‌تر از دستیابی  دیسک است.


E_NON_ROOT_USER=70             #                  باید به عنوان root اجرا شود.
ROOTUSER_NAME=root

MOUNTPT=/mnt/ramdisk           #       با دستور ‎mkdir /mnt/ramdisk‎ ایجاد کنید.
SIZE=2000                      #      تعداد بلوک‌ها‎ (به طور دلخواه تغییر بدهید)
BLOCKSIZE=1024                 #               اندازه بلوک ‎1K‎ (یعنی ‎1024‎ بایت)
DEVICE=/dev/ram0               #                                دستگاه ‎ram‎ اول

username=`id -nu`
if [ "$username" != "$ROOTUSER_NAME" ]
then
  echo "Must be root to run \"`basename $0`\"."
  exit $E_NON_ROOT_USER
fi

if [ ! -d "$MOUNTPT" ]         #       بررسی آنکه نقطه اتصال از قبل وجود دارد،
then                           #+       به طوریکه اگر این اسکریپت چند بار اجرا
  mkdir $MOUNTPT               #+                       اجرا گردد خطا رخ ندهد.
fi

##############################################################################
dd if=/dev/zero of=$DEVICE count=$SIZE bs=$BLOCKSIZE  # دستگاه ‎RAM‎ محتوی zero.
                                                      #       چرا این لازم است؟
mke2fs $DEVICE                 #              ایجاد یک سیستم فایل ‎ext2‎ روی آن.
mount $DEVICE $MOUNTPT         #                                ‎mount‎ کردن آن.
chmod 777 $MOUNTPT             #      فعال کردن دستیابی کاربر عادی به ‎ramdisk‎.
                               #     به هر حال برای ‎unmount‎ آن باید root باشد.
##############################################################################
# لازم است موفقیت دستورات بالا امتحان شود. در غیر این صورت می‌تواند مشکل‌ساز بشود.
#               تمرین: این اسکریپت را طوری ویرایش کنید که قابل اطمینان‌تر بشود.

echo "\"$MOUNTPT\" now available for use."
#    اکنون ‎ramdisk‎ برای ذخیره فایلها، حتی توسط یک کاربر عادی قابل دستیابی است.

# احتیاط، ‎ramdisk‎ ناپایدار است و محتویات آن با reboot یا قطع برق ناپدید می‌شود.
#               هر آنچه را می‌خواهید ذخیره شود به یک دایرکتوری معمولی کپی کنید.

#     بعد از ‎reboot‎، برای دوباره تنظیم کردن ‎ramdisk‎، این اسکریپت را اجرا کنید.
#        دوباره mount کردن ‎/mnt/ramdisk‎ بدون انجام سایر مراحل، عمل نخواهد کرد.

#  این اسکریپت اگر به طور مناسب ویرایش گردد، می‌تواند برای تنظیم خودکار ‎ramdisk‎
#+                      در زمان بالا آمدن سیستم، در ‎/etc/rc.d/rc‎ فراخوانی بشود.
#               به عنوان مثال، شاید روی یک سرویس‌دهنده بانک اطلاعاتی مناسب باشد.

exit 0

علاوه بر تمام موارد بالا، ‎/dev/zero‎ به واسطه باینری‌های ‎ELF‎ ‏(‎Executable and Linking Format‎)‏ یونیکس-لینوکس لازم می‌شود.