آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

آموزش‌های خط فرمانی

این وبلاگ تلاش می‌کند گامی در حد بضاعت در جهت آموزش خط فرمان و اسکریپت‌نویسی پوسته گنو-لینوکس بردارد.

کنترل وجود یک فرمان در مسیر PATH


چگونه می‌توانم تعیین کنم که یک فرمان آیا در جایی از PATH من وجود دارد؟

POSIX فرمان داخلی به نام command تعیین می‌کند، که می‌تواند برای این منظور به کار برود:

# POSIX
if command -v qwerty >/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

در BASH، یک زوج دستور داخلی بیشتر نیز وجود دارد که ممکن است به کار بروند: hash و type. این هم مثالی با استفاده از hash:

# Bash
if hash qwerty 2>/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

یا، اگر ترجیح می‌دهید type:

# Bash
# .بدون در نظر گرفتن دستورات داخلی و غیره می‌کند PATH الزام به جستجوی ‎type -P‎ دستور
if type -P qwerty >/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

پوسته Korn در عوض دارای whence می‌باشد:

# ksh
if whence -p qwerty >/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

دستور داخلی command همچنین برای دستورات داخلی پوسته صحیح را باز می‌گرداند(برخلاف ‎type -P‎). اگر شما باید به طور مطلق فقط PATH را بررسی کنید، تنها روش POSIX انجام تکرار روی آن است:

# POSIX
IsInPath ()
(
  [ $# -eq 1 ] && [ "$1" ] || return 2
  set -f; IFS=:
  for dir in $PATH; do
    [ -z "$dir" ] && dir=.       # رفتار موروثی
    [ -x "$dir/$1" ] && return
  done
  return 1
)

if IsInPath qwerty; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

توجه نمایید که تابع تعریف شده فوق به جای ابروهای معمول، از پرانتزها در اطراف بدنه استفاده می‌کند. این باعث می‌شود بدنه در یک پوسته فرعی اجرا گردد، و این به دلیل آنست که ما می‌خواهیم نیازی به خنثی نمودن ‎set -f‎ یا IFS نداشته باشیم.

رویکرد تکرار کننده در اسکریپت‌های configure نیز استفاده می‌شود. این هم نگارش ساده شده‌ای از یک چنین تستی:

# Bourne
save_IFS=$IFS
IFS=:
found=no
for dir in $PATH; do
  if test -x "$dir/qwerty"; then
    echo "qwerty is installed (in $dir)"
    found=yes
    break
  fi
done
IFS=$save_IFS
if test $found = no; then
  echo "qwerty is not installed"
fi

اسکریپت‌های واقعی configure معمولاً خیلی بیشتر از این پیچیده هستند، چون آنان ممکن است با سیستم‌هایی سر و کار داشته باشند که در آنها ‎$PATH‎ به وسیله کاراکترهای کولن جدا نمی‌شوند، یا سیستم‌هایی که در آنها شاید برنامه‌های اجرایی پسوندهای انتخابی مانند ‎.EXE‎ دارند، یا متغیرهای ‎$PATH‎ که دایرکتوری کاری جاری به عنوان یک رشته تهی در آنها گنجانده شده‌اند و غیره. اگر به چنین مطالبی علاقمند هستید، پیشنهاد می‌کنم یک اسکریپت ‎configure‎ واقعی تولید شده با autoconf گنو را بخوانید. آنها بیش از آن بلند و پیچیده می‌باشند که در این پرسش و پاسخ قرار داده شوند.

فرمان which (که غالباً یک اسکریپت csh است، اگر چه گاهی نیز به صورت باینری کامپایل شده است) برای این منظور قابل اطمینان نیست. which نمی‌تواند یک کد خروج سودمند تنظیم کند، و حتی نمی‌تواند خطاها را در stderr بنویسد. بنابر این، برای مطلع شدن از اجرای موفقیت آمیز آن، باید خروجی‌اش تفکیک بشود(هر جا که خروجی نوشته بشود).

# Bourne.  Last resort -- using which(1)
tmpval=`LC_ALL=C which qwerty 2>&1`
if test $? -ne 0; then
  # این ماشین یک کد خروج غیرصفر ‎which(1)‎ در حال حاضر فرض خواهیم نمود که اگر ‎
  # تنظیم کند، به راستی ناموفق  بوده. هنوز باید حالتی را ببینیم که در آن‎
  #  درست  مثل موفقیت غلط -- یک عدم موفقیت غلط تنظیم می‌کند which(1)‎
  echo "qwerty is not installed.  Please install it."

else
    #  صفر را بازگردانده، که به معنی موفقیت آن نیست. جستجو برای رشته های خطا
    case "$tmpval" in
      *no\ *\ in\ *|*not\ found*|'')
        echo "qwerty is not installed.  Please install it."
        ;;
      *)
        echo "Congratulations -- it seems you have qwerty (in $tmpval)."
        ;;
    esac
fi

توجه نمایید که خروجی ‎which(1)‎ موقعی که دستوری را پیدا نمی‌کند در تمام سکوها یکسان نیست. برای مثال، در ‎HP-UX 10.20‎، این پیغام خطا را چاپ می‌کند ‎no qwerty in /path /path /path ...‎، در ‎OpenBSD 4.1‎، این پیغام خطا را ‎qwerty: Command not found.‎، در دبیان (حداقل ‎3.1‎ تا ‎5.0‎) و SuSE، ابداً چیزی چاپ نمی‌کند، در ‎Red Hat 5.2‎، چاپ می‌کند ‎which: no qwerty in (/path:/path:...)‎، در ‎Red Hat 6.2‎، همان پیغام را می‌نویسد، اما به جای خروجی استاندارد در خطای استاندارد، و در Gentoo، چیزی در stderr می‌نویسد.

ما قویاً پیشنهاد می‌کنیم از which استفاده نکنید. به جای آن یکی از دستورات داخلی یا رویکردهای تکرار را به کار ببرید.


پرسش و پاسخ 81 (آخرین ویرایش ‎2012-03-14 11:57:13‎ توسط pgas)


پرسش و پاسخ شماره ۸۰


چگونه می‌توانم مستعاری ایجاد کنم که یک شناسه دریافت کند؟

نمی‌ توانید. مستعارها در bash بینهایت ابتدایی هستند، و در حقیقت برای هیچ مقصود مهمی مناسب نمی‌باشند. حتی صفحه مستندات bash به طور صریح می‌گوید:

  • هیچ مکانیسمی برای استفاده از شناسه‌ها در جایگزینی متن وجود ندارد. اگر شناسه‌ها مورد نیاز هستند، باید یک تابع پوسته استفاده بشود(توابع پایین را ببینید).

به جای آن از تابع استفاده کنید. برای مثال:

settitle() { case $TERM in *xterm*|*rxvt*) echo -en "\e]2;$1\a";; esac; }

اوه، در ضمن: مستعارها در اسکریپت‌ها مجاز نیستند. آنها فقط در پوسته‌های محاوره‌ای مجاز می‌باشند، و حقیقتاً چنین است چونکه اگر آنها به طور کلی برچیده می‌شدند، کاربران با صدای بلند فریاد می‌کشیدند. اگر شما یک اسکریپت می‌نویسید، همیشه به جای آن از تابع استفاده کنید.


پرسش و پاسخ 80 (آخرین ویرایش ‎2008-11-22 23:25:45‎ توسط GreyCat)


کاربرد grep جهت یافتن کلمات در فایل


چطور می‌توانم grep را برای یافتن سطرهای شامل foo و bar همچنین foo یا bar به کار ببرم؟ یا برای فایل‌های شامل foo و bar، احتمالاً در سطرهای جداگانه؟

این در واقع سه پرسش مختلف است، بنابراین ما پاسخ را به سه قسمت تفکیک کرده‌ایم.

foo و bar در یک سطر

آسانترین روش برای مطابقت با سطرهایی که شامل هر دو رشته foo و bar هستند استفاده از دو فرمان grep می‌باشد:

grep foo | grep bar
grep foo "$myfile" | grep bar   # برای آنهایی که نیاز به نگهداری دستی دارند

این کار همچنین می‌تواند با یک egrep انجام بشود، هر چند(به طوریکه احتمالاً می‌توانید حدس بزنید) این فرمان نمی‌تواند به طور واقعی برای سنجش بیش از دو الگو به کار برود:

egrep 'foo.*bar|bar.*foo'

اگر ترجیح می‌دهید، می‌توانید با یک جمله sed یا awk به این مقصود نائل شوید:

sed -n '/foo/{/bar/p}'
awk '/foo/ && /bar/'

اگر نیاز به راه حل سنجش awk برای تعداد اختیاری الگوها دارید، می‌توانید یک سطر فرمان awk ممتد طرح‌ریزی نمایید:

# bashو ksh93 درپوسته‌های‎
# را ایجاد می‌کند ‎awk "/$1/&&/$2/&&...."‎
# داده‌هایی که می‌خواهند مطابقت شوند باید در ورودی استاندارد باشند‎
# سطرهای انطباق یافته را در خروجی استاندارد می‌نویسد‎
multimatch() {
  (($# < 2)) && { echo "usage: multimatch pat1 pat2 [...]" >&2; return 1; }
  awk "/$1/$(printf "&&/%s/" "${@:2}")"
}

یا، نگارش POSIX:

# POSIX
multimatch() {
  [ $# -lt 2 ] && { echo "usage: multimatch pat1 pat2 [...]" >&2; return 1; }
  __p1=$1
  shift
  awk "/$__p1/$(printf "&&/%s/" "$@")"
}

افسوس، توابع POSIX متغیرهای محلی ندارند. همچنین، در صورتیکه هر یک از الگوها شامل کاراکترهای / باشند، هر دو مورد ناموفق می‌شوند. (اصلاح آن به عنوان یک تمرین برای خواننده واگذار گردیده است.)

یک نگارش POSIX که عبارتهای منظم را در اسکریپت awk تعبیه نمی‌کند.

# POSIX
multimatch() { 
  awk 'BEGIN{for(i=1;i<ARGC;i++) a[i]=ARGV[i]; ARGC=1} {for (i in a) if ($0 !~ a[i]) next; print}' "$@"
}

foo یا bar در یک سطر

روشهای بسیار زیادی برای مطابقت سطرهای شامل foo یا bar وجود دارد. با گزینه ‎ -e‎ می‌توان الگوهای چندتایی را با grep به کار برد:

grep -e 'foo' -e 'bar'

یا می‌توانید یک الگو با egrep (یا ‎grep -E‎) بسازید:

egrep 'foo|bar'
grep -E 'foo|bar'

(نمی‌توانید ازعملگر اتصال | با grep ساده استفاده کنید. این عملگر | فقط در عبارتهای منظم توسعه‌یافته معتبر می‌باشد.)

این کار همچنین می‌تواند با sed، awk، و غیره انجام بشود.

awk '/foo|bar/'

رویکرد awk برتری آن را دارد که به شما اجازه استفاده از سایر ویژگی‌های awk روی سطرهای انطباق یافته را می‌دهد.

مطابقت سطرهایی که شامل هیچ یک از رشته‌های foo و bar نیستند:

grep -E -v 'foo|bar'
# را ترجیح می‌دهند ‎egrep -v 'foo|bar'‎ بعضی اشخاص 

foo و bar در یک فایل، بدون لزوم حضور هر دو در یک سطر

اگر می‌خواهید مطابقت کنید که فایلها (به جای سطرها) شامل هر دو رشته foo و bar هستند، چندین رویکرد عملی وجود دارد. ساده‌ترین(اگر چه ضرورتاً کارآمدترین نیست) دوبار خواندن فایل است:

grep -q foo "$myfile" && grep -q bar "$myfile" && echo "Found both"

راه حل استفاده دوگانه ‎grep -q‎ این مزیت را دارد که در هر نوبت خواندن، در جایی که مورد انطباقی پیدا شود توقف می‌کند، بنابراین اگر یک فایل حجیم داشته باشید، اما کلمات در ابتدای آن باشند، فقط قسمت اول فایل خوانده می‌شود. متأسفانه، اگر انطباق‌ها در انتهای فایل باشند(وضعیت وخیم: در انتهایی‌ترین سطرهای فایل) شما کل فایل را دوبار می‌خوانید.

رویکرد دیگری یکبار خواندن فایل، و حفظ نمودن اثر آنچه دیده‌اید، در ضمن پیشروی در فایل می‌باشد. در awk:

awk '/foo/{a=1} /bar/{b=1} a&&b{print "both found";exit} END{if (a&&b){ exit 0} else{exit 1}}'

این کد فایل را یک بار می‌خواند، موقعی که هر دو الگو منطبق گردیدند توقف می‌کند. مهم نیست چه اتفاقی رخ می‌دهد، پس از آن بلوک END اجرا می‌شود، و مطابق آن وضعیت خروج تنظیم می‌گردد.

اگر می‌خواهید بررسی‌های اضافی در محتویات فایل انجام بدهید، این راهکار awk می‌تواند کاملاً به آسانی وفق داده شود.


پرسش و پاسخ 79 (آخرین ویرایش ‎2011-04-15 12:16:35‎ توسط GreyCat)


تخصیص کلمه عبور توسط اسکریپت!


من می‌خواهم با استفاده ازفرمان passwd یونیکس یک کلمه عبور کاربر را تنظیم کنم، اما چطور آن را اسکریپت کنم؟ ورودی استاندارد را نمی‌خواند!

خوب، اول از همه، من میدانم ممکن است افردای نیز هم اکنون درحال خواندن این مطلب ‌باشند که حتی پرسش را متوجه نمی‌شوند. اینجا، این کد کار نمی‌کند:

{ echo oldpass; echo newpass; echo newpass; } | passwd
# !این کار نمی‌کند

اصلاً کاری نمی‌توانید بکنید که بتواند در bash عملی بشود. ‎passwd(1)‎ از ورودی استاندارد نمی‌خواند. این مطلب تعمدی است. برای حراست از شماست. هرگز کلمات عبور برای قرار گرفتن در برنامه‌ها یا تولید شدن توسط برنامه‌ها در نظر گرفته نشده‌اند. آنها برای آن در نظر گرفته شده‌اند که با انگشتان یک انسان حقیقی، با یک ذکاوت عملیاتی وارد بشوند، و هرگز اصلاً در جایی نوشته نشوند. بنابراین قبل از اینکه ادامه بدهید، احتمالی را که مؤلفین ‎passwd(1)‎ در فکر آن بودند، درنظر بگیرید، و شاید شما نباید سعی در اسکریپت نمودن ورودی ‎passwd(1)‎ بنمایید.

با این وجود، انبوهی پرسش از کاربران به دست ما می‌رسد که آنها چگونه می‌توانند 35 سال امنیت یونیکس را خنثی کنند. و همکاری اشخاصی با راه حل‌های مطلوبِ حذف امنیت را با این صفحه مشاهده می‌کنیم. اگر شما بازهم فکر می‌کنید آنچه می‌خواهید این است، ادامه دهید.

طرح ریزی کلمه عبور درهم ریخته خودتان و نوشتن آن در فایل

اولین رویکرد، ساختن کلمه عبور بهم ریخته خودتان(DES، MD5، Blowfish‎، یا هر چیزی که سیستم عامل شما استفاده می‌کند) با استفاده از ابزارهای غیر استانداردی از قبیل ‎http://wooledge.org/~greg/crypt/‎ یا بسته mkpasswd دبیان/اوبونتو، را شامل می‌شود. سپس باید آن کلمه عبور درهم ریخته را همراه با فیلدهای اضافی در یک سطر از فایل ‎password-hash‎ سیستم محلی خودتان (شاید ‎/etc/passwd‎، یا ‎/etc/shadow‎، یا ‎/etc/master.passwd‎، یا ‎/etc/security/passwd‎، یا ... باشد) بنویسید. این کار نیاز به آن دارد که شما صفحات man در سیستم خود را بخوانید، تا دریابید پسورد بهم‌ریخته کجا قرار می‌گیرد، فایل چه قالب‌بندی نیاز دارد، و سپس کُدی ایجاد کنید که آنرا در آن قالب به تفصیل بنویسد.

یک گونه فرعی آن، مستلزم استفاده از یک ابزار سیستمی خاص برای نوشتن سطرِ کلمه عبور درهم ریخته طراحی شده شما، می‌باشد. برای مثال، در دبیان/اوبونتو، ‎useradd -m joe -s /bin/bash -p "$(mkpasswd "$password")"‎ به طوری که ما فهمیده‌ایم، می‌تواند کارکند.

فریب کامپیوتر به تصور آن که با یک انسان طرف است

دومین رویکرد استفاده از expect یا معادل python آن است. من گمان می‌کنم expect حتی دقیقاً این موضوع را به عنوان یکی از مثالهای رسمی‌اش دارد.

یافتن ابزار سیستمی مخصوص

سرانجام، ابزارهای سیستمی طراحی شده برای این مقصود ممکن است از قبل در سیستم شما موجود باشد. برای مثال، بعضی از سیستمهای گنو-لینوکس دارای فرمان ‎newusers(8)‎ هستند که به طور خاص برای این منظور طراحی شده‌اند، یا ابزار ‎ chpasswd(8)‎ که می‌تواند وادار به انجام انواعی از این کارها بشود. یا ممکن است یک پرچم ‎ --stdin‎ در فرمان passwd خود داشته باشند. همچنین فرمانهایی از قبیل ‎ apropos users‎ یا ‎man -k account‎ را برای دیدن مورد دیگری که شاید وجود داشته باشد امتحان کنید. خلاق باشید.

همچنین پرسش و پاسخ 69 -- می‌خواهم یک ارتباط ssh (یا scp، یا sftp) را خودکار نمایم، اما نمی‌دانم چطور کلمه عبور را ارسال کنم را ببینید.


برای امنیت به ‎ /dev/tty‎ استناد نکنید

در کنار این مطلب، عکس این پرسش نیز مشکلی است. حداقل تحت لینوکس ، پنهان کردن برنامه به نحوی که ترمینال کنترل کننده وادار شود به طور انتزاعی به هر نوع ورودی و خروجی دلخواه شما متصل بشود، امری بدیهی است. این به معنای آنست که از نطر امنیتی بسیار دشوار است تضمین شود که واقعاً یک کاربر با دسترسی محلی است که به طور مستقیم از صفحه کلید، ورودی را به برنامه شما می‌دهد. غالباً اشخاص این کار را با خواندن از‎ /dev/tty ‎ انجام می‌دهند. این درست مانند روشی است که برنامه passwd عمل می‌کند، فقط قدم کوچکی در سست کردن عادات امنیتی نا مناسبی نظیر ذخیره کلمات عبور در فایلهای متن ساده است. کد زیر Bash را اجرا می‌کند، که برنامه‌ای در‎ FD 3 ‎را می‌خواند که به طور غیر هوشمندانه ورودی‌اش را از طریق یک لوله (که به آسانی می‌توانست دقیقاً یک فایل باشد)، با استفاده از یک تابع کتابخانه استاندارد پایتون می‌خواند.

 ~ $ { echo 'o hi there' | python -c 'import pty; pty.spawn(["bash", "/dev/fd/3"])'; } <<"EOF" 3<&0- <&2  
  # ممانعت می‌کند، اثر واقعی ندارد  echo از قطع ارتباط ورودی استاندارد ‎<&2‎ ‎
{
    stty -echo
    read -p 'Password: ' passw
    printf '\n%s\n' "password is: $passw"
    stty echo
} </dev/tty
EOF

o hi there
Password:
password is: o hi there
# نگارش بدون استفاده از پایتون‎

#{ echo 'o hi there' | script -c "bash /dev/fd/3" /dev/null; } <<"EOF" 3<&- 3<&0- <&2   # لینوکس‎
{ echo 'o hi there' | script -q /dev/null bash /dev/fd/3; } <<"EOF" 3<&- 3<&0- <&2      # FreeBSD و Mac OS X در‎
{
    stty -echo
    read -p 'Password: ' passw
    printf '\n%s\n' "password is: $passw"
    stty echo
} </dev/tty
EOF

علاوه بر این، خواندن از ‎ /dev/tt‎y کمی رنجش آور است زیرا طریقه‌ای که کاربران انتظار دارند تغییر مسیرهایشان عمل کنند را نقض می‌کند. پس این کار را انجام ندهید. بهتر است از ‎[[ -t 0 ]]‎ جهت بازرسی tty و رفتار کردن بر طبق موقعیت استفاده کنید. حتی موقعی که یک مدیر سیستم رفتار معینی را انتظار دارد که بر اساس آن I/O را تغییر می‌دهد، این مطلب می‌تواند رنجش آور باشد. اگر شما باید یکی از این ترفندها را به کار ببرید، آن را مستند کنید، و گزینه‌ای برای غیر فعال نمودن رفتار مشروط I/O فراهم نمایید.


پرسش و پاسخ 78 (آخرین ویرایش ‎2013-03-28 10:54:50‎ توسط p54A33276)


نظارت بر عملکرد کاربران


از چه طریق می‌توانم تاریخچه را در فایل log ثبت کنم یا bash را در برابر پاک کردن آن ایمن نمایم؟

اگر شما یک کاربر پوسته هستید که می‌خواهد فعالیت‌های خود را ضبط نماید، FAQ #88 را ملاحظه کنید. اگر شما یک مدیر سیستم می‌باشید که می‌خواهد بداند، موقعی که یک کاربر تاریخچه پوسته‌اش را به ‎ /dev/null‎ فرستاده یا آن را غیر فعال نموده، چطور می‌تواند پی ببرد که او چه دستوراتی را اجرا کرده است، چند مشکل برای این مورد وجود دارد....

اولین موضوع این است:

  • ‎kill -9 $$

این فرمانِ به ظاهر بی ضرر کاری را انجام می‌دهد که شما برای آن متصور بودید: پوسته جاری را متوقف می‌کند. اما، ‎.bash_history‎ فقط موقعی روی دیسک نوشته می‌شود که به bash اجازه داده شود به طور پاکیزه خارج گردد. به این ترتیب، ارسال سیگنال SIGKILL به bash از ثبت رخداد درفایل ‎.bash_history‎ پیش‌گیری می‌کند.

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

  • unset HISTFILE

و تاریخچه حتی اگر کاربر به طور پاکیزه از پوسته خارج گردد نیز نوشته نخواهد شد.

دومین موضوع مجوزها هستند. پوسته bash به عنوان یک کاربر اجرا می‌گردد. این به معنای آنست که کاربر می‌تواند تمام محتویات تولید شده یا به کار گرفته شده توسط پوسته را بخواند و بنویسد. هر محلی که بخواهید bash در آن ثبت وقایع کند باید قابل نوشتن توسط کاربر اجرا کننده bash باشد. هر چند، این واقعاً به معنی توانایی کاربری که سعی در جاسوسی او می‌کنید برای پاک کردن اطلاعات از فایل ثبت وقایع می‌باشد.

سومین موضوع، جایگاه است. فرض کنید شما یک ‎chroot jailزیرنویس1‎ برای کاربران bash خودتان اتخاذ کنید. این ایده شگفت‌انگیزی است، و یک قدم مناسب به طرف امنیت سرویس‌دهنده شما می‌باشد. هرچند که قرار دادن کاربران در یک زندان chroot‎ به طور معکوس بر توانایی گزارش فعالیت های کاربران نیز تأثیر می‌گذارد. وقتی که محدودیت ایجاد شد، کاربر شما فقط می‌تواند در محتوای درون محدوده(jail) ویژه خودش بنویسد. این امر یافتن لاگهای خارجی قابل نوشتن کاربر را آسان می‌سازد، و مهاجم را قادر می‌کند نسبت به حالتی که غیر از این باشد، بسیار آسانتر فایلهای ثبت رخداد پنهان شما را پیدا کند.

این امر شما را در چه جایگاهی قرار می‌دهد؟ متأسفانه، جای خوبی نیست، و مطمئناً آنچه شما می‌خواستید بدانید نیست. اگر شما می‌خواهید تمام دستوراتی که توسط کاربر به bash صادر گردیده را ضبط کنید، اولین نیاز آن، ویرایش bash به طوری است که عملاً آن دستورات را در زمان واقعی، موقعی که اجرا می‌شوند، ضبط کند-- نه وقتی که کاربر قطع ارتباط می‌کند. دومین ضرورت ثبت کردن آنها به طریقی است که کاربر نتواند باز گردد و آنها را پاک کند(که به معنی آنست که در فایل درج نشوند).

گرچه، هنوز این هم قابل اطمینان نیست، زیرا کاربران نهایی به سادگی می‌توانند پوسته‌های خودشان را انتقال بدهند(upload) و آن را به جای bash هک شده شما اجرا کنند. یا شاید آنها یکی از پوسته‌های قبلی دیگر بر روی سیستم شما را به جای آن bash استفاده کنند.

‎Bash 4.1‎ یک گزینه پیکربندی compile-time(حین ترجمه) برای فعال کردن وقایع نگاری تمام فرمانها از طریق ‎syslog(3)‎ دارد. (توجه کنید که این مطلب فقط در صورتی کمک می‌کند که کاربران واقعاً آن پوسته را استفاده کنند که در بالا بحث شد.)

برای آنان که به طور مسلم باید بعضی توانایی‌های وقایع نگاری را در نگارشهای قدیمی‌تر bash داشته باشند: می‌توانید از وصله‌ای که در اینجا قرار داده شده استفاده کنید http://wooledge.org/~greg/bash_logging.txt (این patch توسط _sho_ ارائه شده است-- با مسئولیت خودتان استفاده کنید. نتایج بازبینی کُد همراه بهبودبخشی‌ها در اینجا http://phpfi.com/220302 می‌باشند -- Heiner. متأسفانه به نظر می‌رسد اکنون آن URL منقضی گردیده است.). توجه نمایید که این وصله از syslog استفاده نمی‌کند. وصله به عدم اطلاع کاربر از فایل وقایع نگاری تکیه می‌کند.

جهت یک رویکرد جدی‌تر برای مشکلِ پیگیری آنچه کاربران شما انجام می‌دهند، به جای تمرکز روی پوسته‌ها، BSD process accounting2 (مبتنی بر کرنل) را در نظر بگیرید.


پرسش و پاسخ 77 (آخرین ویرایش ‎2013-01-23 06:08:01‎ توسط geirha)


  1. مترجم: chroot jail یک ویژگی یونیکس است که حالت محدودی از اجرای برنامه را ایجاد می‌کند، که در آن برنامه از داشتن دسترسی کامل به تمام سیستم ممانعت می‌شود و فقط اجازه دیدن محدوده‌ای از فایل سیستم را دارد. از این رو نوعی زندان تعبیر شده است. (بازگشت)

  2. مترجم: process accounting(گزارش پردازش) یک ویژگی گزارش‌گیری است که هنگام کامپایل کرنل می‌توان آن را فعال نمود (بسیاری از سیستم‌های لینوکس طوری پیکربندی گردیده‌اند که این ویژگی در آنها فعال می‌باشد. اما ممکن است در توزیع شما چنین نباشد، در صورتیکه بخواهید با کامپایل مجدد کرنل آن را فعال کنید گزینه مربوط به آن CON‐FIG_BSD_PROCESS_ACCT است. برای اطلاعات دقیق می‌توانید به این بخش از پروژه مستندات لینوکس مراجعه نمایید). اگر این ویژگی در کرنل فعال باشد آنوقت با استفاده از فراخوان سیستم acct می‌‌توان آغاز به کار آن را درخواست نمود، که باعث می‌شود کرنل از هر پردازشی که در سیستم خاتمه می‌یابد یک رکورد در فایل گزارش بنویسد. این رکورد شامل اطلاعاتی در باره پردازشهای اجرا شده (از جمله UID، GID، زمان ایجاد، مدت زمان استفاده از منابع سیستم و غیره) می‌باشد. البته فعال بودن این گزینه فضای قابل توجهی از دیسک را استفاده خواهد نمود(در سیستم‌های شلوغ به ازای هر ساعت تقریباً بیش از یک گیگا بایت)، اما این گزارش موارد استفاده مدیریتی بسیاری دارد که بیان آنها خارج از ظرفیت این صفحه است. (بازگشت)