Bash/examples of functions in scripts

من موسوعة حسوب

إعادة التدوير

ستجد برامج كثيرة على نظامك تستخدم الدوال كطريقة منظمة لمعالجة سلسلة ما من الأوامر، ففي بعض أنظمة لينكس مثلًا ستجد الملف التعريفي etc/rc.d/init/functions/ يشار إليه كمصدر في كل شيفرات init النصية.

وبهذا الأسلوب لا تحتاج إلى كتابة المهام المتكررة سوى مرة واحدة وبشكل عام أيضًا، مهام مثل تفقد ما إن كانت تعمل إحدى المهام، تشغيل أو إيقاف أحد العفاريت (daemons)، وهلم جرا. ثم إذا دعت الحاجة إلى كتابة تلك المهام مرة أخرى فإنك لا تحتاج سوى إعادة تدوير الشيفرة فقط، وليس كتابتها من الصفر.

وتستطيع إنشاء ملف etc/functions/ الخاص بك، والذي سيحتوي كل الدوال التي تستخدمها بانتظام على نظامك والتي قد تكون موزعة على شيفرات مختلفة. وبمجرد أن يكون لديك هذا الملف تستطيع الإشارة إليه في أي برنامج (script) تكتبه بوضع هذا السطر في مكان ما في بداية البرنامج، ثم يمكنك تدوير الدوال بعدها:

. /etc/functions

ضبط المسار

قد تجد هذا الجزء لديك في ملف etc/profile/. هنا تُحدَّد دالة pathmung ثم تستخدم لضبط المسار للمستخدم الجذر وبقية المستخدمين:

pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}

# Path manipulation
if [ `id -u` = 0 ]; then
        pathmunge /sbin
        pathmunge /usr/sbin
        pathmunge /usr/local/sbin
fi

pathmunge /usr/X11R6/bin after

unset pathmunge

وتأخذ تلك الدالة أول وسيط (argument) لها ليكون اسمًا للمسار، ويضاف اسم هذا المسار إلى المسار الحالي إن لم يكن موجودًا من قبل، أما الوسيط الثاني فيحدد إن كان المسار سيضاف قبل أو بعد تعريف متغير PATH الحالي. ولا يضاف لمسار المستخدم العادي إلا usr/X11R6/bin/ ، أما المستخدم الجذر فيحصل على بعض المجلدات الإضافية التي تحتوي أوامر للنظام. ويُلغى ضبط الدالة بعد استخدامها كي لا تظل موجودة.

النسخ الاحتياطي عن بعد

يُستخدم المثال الآتي في إنشاء نسخ احتياطية لكتب، ويعتمد مفاتيح SSH لفتح الاتصال عن بعد. تُحدد هنا دالتان هما buplinux و bupbash ، وتنشئ كل واحدة منهما ملف tar. يُضغط بعدها ويُرسل إلى خادم عن بعد، ثم تُمسح النسخة المحلية بعد ذلك. وتم ضبط البرنامج لينفِّذ دالة bupbash فقط في يوم الأحد.

#/bin/bash

LOGFILE="/nethome/tille/log/backupscript.log"
echo "Starting backups for `date`" >> "$LOGFILE"

buplinux()
{
DIR="/nethome/tille/xml/db/linux-basics/"
TAR="Linux.tar"
BZIP="$TAR.bz2"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"

cd "$DIR"
tar cf "$TAR" src/*.xml src/images/*.png src/images/*.eps
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
echo -e "Done backing up Linux course:\nSource files, PNG and EPS images.\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}

bupbash()
{
DIR="/nethome/tille/xml/db/"
TAR="Bash.tar"
BZIP="$TAR.bz2"
FILES="bash-programming/"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"

cd "$DIR"
tar cf "$TAR" "$FILES"
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"

echo -e "Done backing up Bash course:\n$FILES\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}

DAY=`date +%w`

if [ "$DAY" -lt "2" ]; then
  echo "It is `date +%A`, only backing up Bash course." >> "$LOGFILE"
  bupbash
else
  buplinux
  bupbash
fi


echo -e "Remote backup `date` SUCCESS\n----------" >> "$LOGFILE"

يعمل هذا البرنامج عبر cron، بمعنى أنه يعمل دون تدخل المستخدم، لهذا فإننا نعيد توجيه الخطأ القياسي من أمر scp إلى dev/null/. وربما يرى البعض أن كل الخطوات المنفصلة تلك يمكن دمجها في أمر مثل:

tar c dir_to_backup/ | bzip2 | ssh server "cat > backup.tar.bz2"

لكن إن كنت تريد النتائج التي يمكن استعادتها عند فشل البرنامج، فإن ذلك الأمر المختصر لن يفيدك. أيضًا، يماثل تعبير command &> file تعبيرَ command > file 2>&1