فصل 29- ‏ ‎/dev‎ و ‎/proc‎

‎29.2‎-‏ ‎/proc‎

شاخه ‎/proc‎ در حقیقت یک سیستم فایل کاذب است. فایل‌ها در ‎/proc‎ پردازش‌های کرنل و سیستم درحال اجرای فعلی را بازتاب می‌دهند و شامل اطلاعات و آماری در باره آنها هستند.

bash$ cat /proc/devices

Character devices:
   1 mem
   2 pty
   3 ttyp
   4 ttyS
   5 cua
   7 vcs
  10 misc
  14 sound
  29 fb
  36 netlink
 128 ptm
 136 pts
 162 raw
 254 pcmcia

 Block devices:
   1 ramdisk
   2 fd
   3 ide0
   9 md


bash$ cat /proc/interrupts

           CPU0       
   0:      84505          XT-PIC  timer
   1:       3375          XT-PIC  keyboard
   2:          0          XT-PIC  cascade
   5:          1          XT-PIC  soundblaster
   8:          1          XT-PIC  rtc
  12:       4231          XT-PIC  PS/2 Mouse
  14:     109373          XT-PIC  ide0
 NMI:          0 
 ERR:          0

bash$ cat /proc/partitions

major minor  #blocks  name    rio rmerge rsect ruse wio wmerge wsect wuse running use aveq

    3     0    3007872 hda 4472 22260 114520 94240 3551 18703 50384 549710 0 111550 644030
    3     1      52416 hda1 27 395 844 960 4 2 14 180 0 800 1140
    3     2          1 hda2 0 0 0 0 0 0 0 0 0 0 0
    3     4     165280 hda4 10 0 20 210 0 0 0 0 0 210 210
    ...

bash$ cat /proc/loadavg

0.13 0.42 0.27 2/44 1119


bash$ cat /proc/apm

1.16 1.2 0x03 0x01 0xff 0x80 -1% -1 ?


bash$ cat /proc/acpi/battery/BAT0/info

present:                 yes
 design capacity:         43200 mWh
 last full capacity:      36640 mWh
 battery technology:      rechargeable
 design voltage:          10800 mV
 design capacity warning: 1832 mWh
 design capacity low:     200 mWh
 capacity granularity 1:  1 mWh
 capacity granularity 2:  1 mWh
 model number:            IBM-02K6897
 serial number:            1133
 battery type:            LION
 OEM info:                Panasonic
  
 
bash$ fgrep Mem /proc/meminfo

MemTotal:       515216 kB
 MemFree:        266248 kB
         

اسکریپت‌های پوسته می‌توانند داده‌ها را از برخی فایل‌های ‎/proc‎ استخراج نمایند. ‎[1]‎

FS=iso                       #آیا سیستم فایل ISO در کرنل نگهداری می‌شود؟

grep $FS /proc/filesystems   # iso9660

kernel_version=$( awk '{ print $3 }' /proc/version )

CPU=$( awk '/model name/ {print $5}' < /proc/cpuinfo )

if [ "$CPU" = "Pentium(R)" ]
then
  run_some_commands
  ...
else
  run_other_commands
  ...
fi



cpu_speed=$( fgrep "cpu MHz" /proc/cpuinfo | awk '{print $4}' )
#سرعت عمل فعلی cpu روی ماشین شما(به ‎MHz‎). در یک لپ تاپ
#  ممکن است موقع استفاده از باطری یا برق AC تغییر کند.

#!/bin/bash
# get-commandline.sh
# به دست آوردن پارامترهای خط فرمان یک پردازش.

OPTION=cmdline

# شناسایی کردن ‎PID‎.
pid=$( echo $(pidof "$1") | awk '{ print $1 }' )
#         از چندین نمونه    ‎^^^^^^^^^^^^^^^^^^‎ تهیه فقط اولی

echo
echo "Process ID of (first instance of) "$1" = $pid"
echo -n "Command-line arguments: "
cat /proc/"$pid"/"$OPTION" | xargs -0 echo
#                          ^^^^^^^^^^^^^^^  خروجی را قالب‌بندی می‌کند 
#   (‎Han Holl‎ برای این مرتب کردن متشکرم!)

echo; echo


# برای مثال:
# sh get-commandline.sh xterm

+

devfile="/proc/bus/usb/devices"
text="Spd"
USB1="Spd=12"
USB2="Spd=480"


bus_speed=$(fgrep -m 1 "$text" $devfile | awk '{print $9}')
#                 ‎^^^^‎ .توقف پس از اولین انطباق

if [ "$bus_speed" = "$USB1" ]
then
  echo "USB 1.1 port found."
  # انجام کاری متناسب برای ‎USB 1.1‎
fi


حتی کنترل برخی دستگاه‌های جانبی با فرستادن فرمان‌ها به شاخه ‎/proc‎ امکان‌پذیر است.
root# echo on > /proc/acpi/ibm/light

این دستور Thinklight را در بعضی مدل‌های Thinkpad مارک ‎‎IBM/Lenovo‎ روشن می‌کند. (ممکن است در همه توزیع‌های لینوکس کار نکند.)

البته، هنگام نوشتن در ‎/proc‎، احتیاط شرط عقل است.

شاخه ‎/proc‎ محتوی شاخه‌های فرعی با نام‌های عددی غیرمعمولی است. هر یک از این نام‌ها به ‎ID‎ پردازش یک پردازش در حال اجرا مربوط می‌شود. داخل هر کدام از این شاخه‌های فرعی تعدادی فایل وجود دارد که اطلاعات مفیدی در باره پردازش متناظر نگهداری می‌کنند. فایل‌های stat و status آمار مربوط به پردازش در حال اجرا را نگهداری می‌کنند، فایل cmdline شناسه‌های خط فرمان را که پردازش با آنها فراخوانی گردیده حفظ می‌کند، و فایل exe یک پیوند نمادین به نام مسیر کامل فراخوانی پردازش است. چند فایل دیگر از این قبیل وجود دارد، اما به نظر می‌رسد از دیدگاه اسکریپت‌نویسی این‌ها جالب‌ترین موارد هستند.

مثال ‎29-3‎. یافتن پردازش مرتبط با یک ‎PID‎

#!/bin/bash
# pid-identifier.sh:
# نام مسیر کامل برای پردازش مرتبط با ‎pid‎ را به دست می‌آورد.

ARGNO=1              # تعداد شناسه‌های مورد انتظار اسکریپت.
E_WRONGARGS=65
E_BADPID=66
E_NOSUCHPROCESS=67
E_NOPERMISSION=68
PROCFILE=exe

if [ $# -ne $ARGNO ]
then
  echo "Usage: `basename $0` PID-number" >&2  # Error message >stderr.
  exit $E_WRONGARGS
fi  

pidno=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )
# pid یعنی فیلد شماره 1 را در لیست‌گیری ps بررسی می‌کند. سپس
#  تضمین می‌کند پردازش واقعی باشد نه پردازش فراخوانی شده با
# این اسکریپت، ‎grep $1‎ انتهایی، این احتمال را فیلتر می‌کند.
#
#    pidno=$( ps ax | awk '{ print $1 }' | grep $1 )
#     نیز به طوری که ‎Teemu Huovila‎ اشاره نموده کار می‌کند.

if [ -z "$pidno" ]  # اگر بعد از فیلتر کردن، رشته‌ای با طول صفر نتیجه شود،
then                #+    یعنی پردازشی با ‎pid‎ داده شده، در حال اجرا نیست.
  echo "No such process running."
  exit $E_NOSUCHPROCESS
fi  

#                   به طور جایگزین:
# if ! ps $1 > /dev/null 2>&1
# then      #پردازش متناظر pid مفروض در حال اجرا نیست.
#   echo "No such process running."
#   exit $E_NOSUCHPROCESS
# fi

#    برای ساده کردن تمام فرایند از pidof استفاده کنید.


if [ ! -r "/proc/$1/$PROCFILE" ]  # کنترل مجوز خواندن.
then
  echo "Process $1 running, but..."
  echo "Can't get read permission on /proc/$1/$PROCFILE."
  exit $E_NOPERMISSION  # کاربر عادی به برخی از فایل‌ها در ‎/proc‎ دسترسی ندارد.
fi  

#                            دو تست انتهایی می‌توانند با این مورد تعویض بشوند:
# if ! kill -0 $1 > /dev/null 2>&1  #   ‎0‎ یک سیگنال نیست، اما این تست می‌کند که
                                    #آیا ارسال یک سیگنال به پردازش مقدور است.
#    then echo "PID doesn't exist or you're not its owner" >&2
#    exit $E_BADPID
#    fi



exe_file=$( ls -l /proc/$1 | grep "exe" | awk '{ print $11 }' )
# یا       ‎exe_file=$( ls -l /proc/$1/exe | awk '{print $11}' )‎
#
# ‎/proc/pid-number/exe‎ یک پیوند نمادین به
#+     نام مسیر کامل فراخوانی پردازش است.

if [ -e "$exe_file" ]  # اگر ‎/proc/pid-number/exe‎ وجود دارد،
then                   #+  آنوقت پردازش متناظر آن موجود است.
  echo "Process #$1 invoked by $exe_file."
else
  echo "No such process running."
fi  


#  این اسکریپت پیچیده *تقریباً* می‌تواند با یک سطر
#.تعویض بشود ps ax | grep $1 | awk '{ print $5 }'
#                     اما، این کار نخواهد کرد...
#+   زیرا فیلد پنجم ‎ps‎ برابر ‎argv[0]‎ پردازش است،
#+                       نه مسیر فایل قابل اجرا.
#
#          به هر حال یکی از موارد زیر کار می‌کند.
#  find /proc/$1/exe -printf '%l\n'
#  lsof -aFn -p $1 -d txt | sed -ne 's/^n//p'

#شرح و تفسیر اضافی نوشته ‎Stephane Chazelas‎ است.

exit 0

مثال ‎29-4‎. وضعیت اتصال آنلاین

#!/bin/bash
# connect-stat.sh
# توجه نمایید که این اسکریپت برای کار کردن با یک
#+اتصال ‎wireless‎ شاید نیاز به ویرایش داشته باشد.

PROCNAME=pppd        #           ppp daemon
PROCFILENAME=status  #  فایلی که باید بررسی شود.
NOTCONNECTED=85
INTERVAL=2           #روزآمد کردن در هر دوثانیه.

pidno=$( ps ax | grep -v "ps ax" | grep -v grep | grep $PROCNAME |
awk '{ print $1 }' )

#                   پیدا کردن شماره پردازش ‎pppd‎‏، برنامه کمکی ‎ppp‎.
#   سطرهای پردازش تولید شده به وسیله خود جستجو، باید فیلتر بشوند.
#
#   به هر حال، همانطور که ‎Oleg Philon‎ اشاره می‌کند، این رشته فرمان
#+     می‌تواند با استفاده از ‎pidof‎ به طور قابل ملاحظه‌ای ساده‌ بشود.
#    pidno=$( pidof $PROCNAME )
#
#                                                    نتیجه اخلاقی:
#+موقعی که رشته فرمان خیلی پیچیده می‌شود، یک راه میانبر پیدا کنید.


if [ -z "$pidno" ]   #  اگر ‎pid‎ نیست، پس پردازش در حال اجرا نیست.
then
  echo "Not connected."
# exit $NOTCONNECTED
else
  echo "Connected."; echo
fi

while [ true ]    #حلقه بی‌پایان، اینجا اسکریپت می‌تواند بهینه شود.
do

  if [ ! -e "/proc/$pidno/$PROCFILENAME" ]
  #در مدت زمانی که پردازش در حال اجرا است، فایل status وجود دارد.
  then
    echo "Disconnected."
#   exit $NOTCONNECTED
  fi

netstat -s | grep "packets received"    #تهیه برخی آمارهای اتصال.
netstat -s | grep "packets delivered"


  sleep $INTERVAL
  echo; echo

done

exit 0

# به طوریکه معلوم است، این اسکریپت باید با ‎Control-C‎ خاتمه یابد.

#                             تمرین‌ها:
#                           ------------
#       اسکریپت را طوری بهینه کنید که با زدن کلید q خارج بشود.
#                با روش‌های دیگری اسکریپت را کاربر پسندتر کنید.
# اسکریپت را برای کار کردن با اتصال‌های ‎wireless/DSL‎ اصلاح کنید.

WARNINGبه طور کلی، نوشتن در فایل‌های داخل ‎/proc‎ خطرناک است، چون این کار می‌تواند باعث خراب کردن سیستم فایل یا از کار افتادن ماشین بشود.

یادداشت‌ها

‎[1]‎

برخی فرمان‌های سیستم، از قبیل procinfo‏، free‏، vmstat‏، lsdev، و uptime نیز این کار را انجام می‌دهند.