یکی از طولانی ترین و زمان گیرترین مراحل فرآیند بوت برای هر رایانه ای این است که هنگام راه اندازی دوباره، رایانه به صورت کامل خاموش می شود و CPU به ابتدایی ترین مرحله ی راه اندازی یعنی BIOS (Basic Input Output System) می رود. BIOS و POST (Power-On Self-Test) شامل چندین مرحله از جمله آزمایش و شناسایی سخت افزار و آماده سازی اولیه می شود. هنگام ری استارت این مراحل غیر از گرفتن زمان فایده ی دیگری ندارند زیرا قبلا یک بار طی شده اند.
این همان جاییست که kexec وارد می شود، kexec به شما این امکان را می دهد که از کرنل در حال اجرا مستقیما به کرنل دیگری (یا همان کرنل) بوت کنید. این بدان معنیست که هنگام راه اندازی دوباره دیگر خبری از مراحل BIOS، POST، GRUB و انتخاب سیستم عامل نخواهد بود و گنو/لینوکس شما در سریعترین زمان ممکن ری استارت می شود. در اینجا روش استفاده از kexec را برای دو توزیع اوبونتو و آرچ توضیح خواهیم داد (البته روش کلی کار و دستورات در توزیع های دیگر هم باید مشابه باشد).
kexec در اوبونتو :
ابتدا بسته ی kexec-tools را نصب کنید :
حال می توانید با استفاده از دستور زیر کرنل مورد نظر خود را در حافظه (RAM) بارگذاری کنید :
KERNEL-PATH، KERNEL-OPTIONS و INITRD-PATH به ترتیب مسیر کرنل، آپشن های کرنل و مسیر فایل initrd هستند که به راحتی می توانید آن ها را در مسیر /boot، خروجی دستور cat /proc/cmdline و یا خطوط مربوط به ورودی کرنل، موجود در فایل /boot/grub/grub.cfg بیابید. برای مثال با توجه به خطوط زیر در فایل grub.cfg :
در نتیجه دستور به شکل زیر در می آید :
و در نهایت با دستور زیر به کرنل جدید بوت و یا کرنل در حال اجرا را ری بوت کنید :
دو دستور بالا را می توانید در یک فایل به عنوان اسکریپت ذخیره و برای ری استارت سریع از آن استفاده نمایید. برای مثال فایلی به نام qreboot ساخته و خطوط زیر را در آن قرار می دهیم :
سپس آن را به مسیر /usr/local/sbin منتقل کرده و به آن دسترسی اجرایی می هیم :
حال کافیست بنویسیم sudo qreboot و Enter کنیم.
kexec در آرچ :
استفاده از kexec در آرچ نیز شبیه اوبونتوست با این تفاوت که اسکریپت های rc به صورت پیش فرض از kexec پشتیبانی می کنند. به این معنی که kexec می تواند مستقیما از طریق دستور reboot (یا دستورات مشابه) مورد استفاده قرار گیرد. برای استفاده از این اسکریپت ها kexec را به آرایه ی DAEMONS موجود در فایل /etc/rc.conf اضاف کنید. البته پیش از آن باید kexec را نصب کنید :
با استفاده از خود kexec هم می توان ری بوت را انجام داد، با اجرای دستوری شبیه دستور زیر :
توجه کنید که تفاوت دستور بالا با آنچه در مورد اوبونتو بیان کردیم این است که به محض اجرای دستور بالا سیستم ری بوت می شود (حالت های مختلف استفاده از دستور kexec). به عنوان مثال برای بوت از کرنل پیش فرض آرچ به کرنل pf، من از دستور زیر استفاده می کنم :
علاوه بر این اسکریپت هایی به نام Bootloader scripts نیز وجود دارند که اطلاعات مربوط به کرنل را از منوی گراب می خوانند و در kexec به کار می برند. یکی از این اسکریپت ها را برای مثال در مسیر /usr/local/sbin/kexec-reboot ذخیره کنید و با استفاده از chmod +x به آن قابلیت اجرایی بدهید. اسکریپت، شماره ی ورودی های موجود در گراب را به عنوان اولین پارامتر خود دریافت می کند. به عنوان مثال برای بوت به دومین ورودی موجود در منوی گراب دستور زیر را اجرا کنید :
اسکریپت بوت لودر برای GRUB1 :
اسکریپت بوت لودر برای GRUB2 :
این همان جاییست که kexec وارد می شود، kexec به شما این امکان را می دهد که از کرنل در حال اجرا مستقیما به کرنل دیگری (یا همان کرنل) بوت کنید. این بدان معنیست که هنگام راه اندازی دوباره دیگر خبری از مراحل BIOS، POST، GRUB و انتخاب سیستم عامل نخواهد بود و گنو/لینوکس شما در سریعترین زمان ممکن ری استارت می شود. در اینجا روش استفاده از kexec را برای دو توزیع اوبونتو و آرچ توضیح خواهیم داد (البته روش کلی کار و دستورات در توزیع های دیگر هم باید مشابه باشد).
kexec در اوبونتو :
ابتدا بسته ی kexec-tools را نصب کنید :
کد PHP:
sudo apt-get install kexec-tools
کد PHP:
sudo kexec -l KERNEL-PATH --append='KERNEL-OPTIONS' --initrd=INITRD-PATH
کد PHP:
menuentry 'Ubuntu, with Linux 3.2.0-24-generic' --class ubuntu --class gnu-linux --class gnu --class os {
recordfail
gfxmode $linux_gfx_mode
insmod gzio
insmod part_msdos
insmod ext2
set root='(hd1,msdos5)'
search --no-floppy --fs-uuid --set=root 357b9ff8-dcb0-4717-9102-5b3ecaa23595
linux /boot/vmlinuz-3.2.0-24-generic root=UUID=357b9ff8-dcb0-4717-9102-5b3ecaa23595 ro crashkernel=384M-2G:64M,2G-:128M quiet splash $vt_handoff
initrd /boot/initrd.img-3.2.0-24-generic
}
KERNEL-PATH = /boot/vmlinuz-3.2.0-24-generic
KERNEL-OPTIONS = root=UUID=357b9ff8-dcb0-4717-9102-5b3ecaa23595 ro quiet splash $vt_handoff
INITRD-PATH = /boot/initrd.img-3.2.0-24-generic
KERNEL-OPTIONS = root=UUID=357b9ff8-dcb0-4717-9102-5b3ecaa23595 ro quiet splash $vt_handoff
INITRD-PATH = /boot/initrd.img-3.2.0-24-generic
در نتیجه دستور به شکل زیر در می آید :
کد PHP:
sudo kexec -l /boot/vmlinuz-3.2.0-24-generic --append='root=UUID=357b9ff8-dcb0-4717-9102-5b3ecaa23595 ro quiet splash $vt_handoff' --initrd=/boot/initrd.img-3.2.0-24-generic
کد PHP:
kexec -e
کد PHP:
#!/bin/bash
kexec -l /boot/vmlinuz-3.2.0-24-generic --append='root=UUID=357b9ff8-dcb0-4717-9102-5b3ecaa23595 ro crashkernel=384M-2G:64M,2G-:128M quiet splash $vt_handoff' --initrd=/boot/initrd.img-3.2.0-24-generic
kexec -e
کد PHP:
chmod +x /usr/local/sbin/qreboot
kexec در آرچ :
استفاده از kexec در آرچ نیز شبیه اوبونتوست با این تفاوت که اسکریپت های rc به صورت پیش فرض از kexec پشتیبانی می کنند. به این معنی که kexec می تواند مستقیما از طریق دستور reboot (یا دستورات مشابه) مورد استفاده قرار گیرد. برای استفاده از این اسکریپت ها kexec را به آرایه ی DAEMONS موجود در فایل /etc/rc.conf اضاف کنید. البته پیش از آن باید kexec را نصب کنید :
کد PHP:
sudo pacman -S kexec-tools
کد PHP:
kexec /boot/vmlinuz-linux --append='root=/dev/disk/by-label/<label> ro' --initrd=/boot/initramfs-linux.img</label>
کد PHP:
sudo kexec /boot/vmlinuz-linux-pf --append='root=/dev/sdc1 ro fastboot ipv6.disable=1 init=/usr/sbin/e4rat-preload-lite' --initrd=/boot/initramfs-linux-pf.img
کد PHP:
sudo /usr/local/sbin/kexec-reboot 2
کد PHP:
#!/bin/bash
# This script loads a kernel from the GRUB menu and reboots.
# The error checking is very basic.
# Written by Isaac G, 2010
die ()
{
tput setaf 1 # Red text
echo "Error: $@" >&2
tput sgr0 # Reset
exit 1
}
(( UID != 0 )) && die "You need to be superuser"
unset number
# Use the first parameter or show a menu if none is specified
if [[ $1 ]] ; then
# Make sure the selected number is an integer
[[ $1 = *[^0-9]* ]] && die "The selected parameter is not a number"
number=$1
else
# Nothing selected; pull up a list of options from the grub menu
oldIFS="$IFS"
IFS=$'\n'
# Get the titles
options=( $(awk '$1 == "title" {for (i = 2; i <= NF; i++) printf "%s ", $i; printf "\n";}' /boot/grub/menu.lst ) )
# Ask the user to select one
select title in "${options[@]}" ; do
for ((i = 0; i < ${#options[@]}; i++)); do
[[ $title == "${options[i]}" ]] && number=$((i + 1)) && break
done
[[ $number ]] && break
done
IFS="$oldIFS"
fi
unset kernel
unset initrd
unset append
item=0
# Parse GRUBs menu.lst
while read key val extra; do
[[ $key = "title" ]] && ((item++)) # Count the number of title's
(( item == number )) || continue # Wait until the right number
[[ $key = "kernel" ]] && kernel="$val" && append="$extra"
[[ $key = "initrd" ]] && initrd="$val"
done < /boot/grub/menu.lst
[[ $kernel ]] || die "No such kernel with that number"
# http://stackoverflow.com/questions/2167558/give-the-mount-point-of-a-path
root="$(df /boot | tail -n 1 | awk '{ print $NF}')"
set -- "$root$kernel"
[[ -n "${initrd+set}" ]] && set -- "$@" --initrd="$root$initrd"
set -- "$@" --append="$append"
kexec "$@"
اسکریپت بوت لودر برای GRUB2 :
کد PHP:
#!/bin/bash
# This script loads a kernel from the GRUB 2 menu and reboots.
# The error checking is very basic.
# Written by Isaac G, 2010
# Modified by Greg Fitzgerald, 2011
die ()
{
tput setaf 1 # Red text
echo "Error: $@" >&2
tput sgr0 # Reset
exit 1
}
(( UID != 0 )) && die "You need to be superuser"
unset number
# Use the first parameter or show a menu if none is specified
if [[ $1 ]] ; then
# Make sure the selected number is an integer
[[ $1 = *[^0-9]* ]] && die "The selected parameter is not a number"
number=$1
else
# Nothing selected; pull up a list of options from the grub menu
oldIFS="$IFS"
IFS=$'\n'
# Get the menuentrys
options=( $(awk '$1 == "menuentry" {for (i = 2; i <= NF; i++) printf "%s ", $i; printf "\n";}' /boot/grub/grub.cfg ) )
# Ask the user to select one
select menuentry in "${options[@]}" ; do
for ((i = 0; i < ${#options[@]}; i++)); do
[[ $menuentry == "${options[i]}" ]] && number=$((i + 1)) && break
done
[[ $number ]] && break
done
IFS="$oldIFS"
fi
unset kernel
unset initrd
unset append
item=0
# Parse GRUBs grub.cfg
while read key val extra; do
[[ $key = "menuentry" ]] && ((item++)) # Count the number of menuentry's
(( item == number )) || continue # Wait until the right number
[[ $key = "linux" ]] && kernel="$val" && append="$extra"
[[ $key = "initrd" ]] && initrd="$val"
done < /boot/grub/grub.cfg
[[ $kernel ]] || die "No such kernel with that number"
# Load the kernel
kexec -l "/boot$kernel" --initrd="/boot$initrd" --append="$append"
## Sync the disks
sync
## Reboot
kexec -e