開機自啟動:從busybox到debian


需要在mint上設置opensips的開機自啟動,翻了半天資料還是一知半解。最后在opensips的官方文檔,查到用下面的語句,添加自啟動成功。不過貌似還是會有啟動不成功,沒有仔細測試過。

update-rc.d opensips default 99

早上抽空看了下這個話題,粗略記錄。

 

從kernel和busybox開始說起

那,咱盡量把故事給串起來。先說說kernel里面設計的init的執行過程,

1) 根據啟動參數來執行init,“啟動參數”包括initrd或initramfs里面的init,以及cmdline里面的init參數。

2) 如果未能成功init,則繼續執行“/sbin/init”。

6) 如果失敗,則繼續尋找並執行“/etc/init”,“/bin/init”,“/bin/sh”等腳本,還是未能進入init,則報panic。

如果使用busybox的話,一般會把/sbin/init軟連接到busybox去,讓busybox來完成init工作。而我們知道busy的init基本是以來inittab完成的,inittab不存在的時候,它會去找rcS。下面是一個busybox inittab的例子。

# Executed on startup
::sysinit:/etc/rc.d/rc.sysinit
# Start an "askfirst" shell on the console (whatever that may be)
ttyS0::askfirst:/sbin/getty -L ttyS0 115200 vt100
# Stuff to do when restarting the init process
::restart:/sbin/init
# Run daemons
::wait:/usr/etc/rc.d/rc start
# Stuff to do before rebooting
::shutdown:/etc/rc.d/rc stop
::shutdown:/etc/rc.d/rc.stop
::shutdown:/bin/umount -a -r
null::respawn:/bin/infctld -m -c
null::respawn:/bin/lighttpd -D -f /etc/lighttpd.conf
null::respawn:/bin/dropbear -F -d /etc/persistent/dropbear_dss_host_key -r /etc/

針對這個inittab,根據busybox中各action的執行順序,具體分析下busybox都做了什么:

1、先是執行sysinit,所以這里是新開了一個進程,執行/etc/rc.d/rc.sysinit;結束之前是不會往下執行的。

2、然后執行wait和once,再這里是/etc/rc.d/rc start,並等待它結束(termination)。

3、然后執行askfirst和respawn。askfirst是在ttys0打開調試口,然后等待我們敲入一個回車;respawn是啟動了幾個重要的程序。這兩個action一直在監視自己啟動的子進程是否退出,如果退出,重新啟動他們。

 

debian里的init.d

這里猜測啟動后init的過程和上面的一樣,先對這里的init有個感官認識,

$ which init
/sbin/init
$ file /sbin/init
/sbin/init: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xb9aa33d2067c8a0f80336122dd6249758f61fdaa, stripped

man inittab描述,inittab本身是init命令的配置腳本;init提供了一個general的dispatcher。我們先看看inittab里面都有什么:

$ cat inittab
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.
id:2:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS

# What to do in single-user mode.
~~:S:wait:/sbin/sulogin

# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.

l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin

# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now

# Action on special keypress (ALT-UpArrow).
#kb::kbrequest:/bin/echo "Keyboard Request--edit /etc/inittab to let this work."

# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop

# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
#
# Format:
#  <id>:<runlevels>:<action>:<process>
#
# Note that on most Debian systems tty7 is used by the X Window System,
# so if you want to add more getty's go ahead but skip tty7 if you run X.
#
1:2345:respawn:/sbin/getty --noclear 38400 tty1 
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100

# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3


#Spawn a getty on Raspberry Pi serial line
T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

順序分析下這個inittab:

1、顯示sysinit,哈,這里的sysinit是執行/etc/init.d/rcS。然后我查看rcS發現,它事實上是執行了/etc/init.d/rc S。然后cat /etc/rcS.d/README,看到下面這段話:

The scripts in this directory whose names begin with an 'S' are executed once when booting the system, even when booting directly into single user mode.

The scripts are all symbolic links whose targets are located in /etc/init.d/ .

To disable a script in this directory, rename it so that it begins with a 'K' and run 'update-rc.d script defaults' to update the order using the script dependencies.

那,所以就是,這個目錄下的軟連接指向的腳本,都是要在系統init的一開始就要執行的。如果要disable某一項,重命名,把它名字里的S給改成K。

2、initdefault行定義了要執行的runlevel,init會根據它去決定執行具體的哪些腳本;最終是執行我們放在/etc/rc*run_level*.d文件夾里的軟連接,如上一條,執行的是rcS.d下的腳本。

3、接下來是wait、respawn等這些。

事實上,它和上面busybox的init不同之處,就在於它多出runlevel;同時,我們想要啟動的腳本都添加了軟連接到rc*run_level*.d文件夾下,不同runlevel下,會去用wait這一action依次去執行相應目錄下的所有腳本。

突然醒悟,原來這里的rc是runlevel changes的意思。

 

新的upstart

debian相關話題:http://refspecs.linuxfoundation.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/tocsysinit.html

upstart是新的管理開機自啟動程式的方法。ubuntu的文檔說,從6.1開始,他們就在用這種新方法管理開機自啟動了。而且upstart和上面的init過程是不沖突的:

1、upstart相關的文件夾是/etc/init。他們本身只是為了支持service方式存在的。

2、/etc/init.d里面存放着真正的啟動腳本,是sysinit和upstart共用的。事實上,很多服務,在執行servie myservice start時,只是打印了一個“使用 service方式啟動”,其余的工作還是由init.d下的腳本完成的。

3、我們可以通過修改/etc/default里面的一些配置文件,來實現對sysint或者upstart的控制。

4、/etc/init/rc-init.conf控制着upstart的行為,手動配置;updata-rc.d則是對傳統的sysinit進行配置,改變rc.d下面的文件等。

當我們需要想upstart添加或刪除一個service時,我們需要:

1、upstart沒有runlevel的概念,在這里,所有的都是由‘依賴關系’驅動的事件。添加一個service意味着需要往/etc/init里面添加一個config文件,同時,有需要的話,可以在/etc/default文件夾添加一個配置文件。

2、需要移除一個service時,如果在/etc/default沒有配置文件,那么直接編輯/etc/init/下相應的配置文件即可。

一些重要的upstart用到的工具:

Controlling Services - interchangeable with the "service" command

initctl - can use in place of "service" with the commands bellow. Run initctl help.

start - start a service

stop - stop a service

reload - sends a SIGHUP signal to running process

restart - restarts a service without reloading its job config file

status - requests status of service

Rebooting and Powering off the system

halt - shutdown the system then power off

poweroff - shutdown the system then power off

reboot - reboot the system

shutdown - bring the system down

Misc Upstart Commands - you generally don't use these directly

init - Upstart process management daemon 

runlevel - Backward compatibility with traditional runlevels

telinit - Backward compatibility with traditional runlevels

upstart-udev-bridge - Bridge between upstart and udev

 下面是一個service的config腳本,更詳細的可以參考《upstart cookbook》,或者是查看man 5 init:

# myservice - myservice job file

description "my service description"
author "Me <myself@i.com>"

# Stanzas
#
# Stanzas control when and how a process is started and stopped
# See a list of stanzas here: http://upstart.ubuntu.com/wiki/Stanzas#respawn

# When to start the service
start on runlevel [2345]

# When to stop the service
stop on runlevel [016]

# Automatically restart process if crashed
respawn

# Essentially lets upstart know the process will detach itself to the background
expect fork

# Run before process
pre-start script
    [ -d /var/run/myservice ] || mkdir -p /var/run/myservice
    echo "Put bash code here"
end script

# Start the process
exec myprocess

 it's time to go to bed :)

 

最新的systemd

systemd之所以叫這個名字,很大程度上是因為它名字里有個d,sorry,我說的是它是嚴重依賴於D-bus的。

有人說以后的linux distribution基本都會用systemd了,理由之一是sysinit是從unix繼承來的,理由之二是sysinit已經統治很久了,理由之三是sysinit做了很多多余的事,理由之四是sysinit依賴shell進而影響了效率。。。sysinit應用還是很廣的,取代也不會是一兩天的事情,但是了解下極有前途的新秀也不錯。

它是替代了init哦!init不只是sysV-style或者是BSD-style,還有其它改進的版本;我們上面介紹到的就是sysV-style,兩者最大區別是,sysV有runlevel的概念,而且是遵照inittab行事。

好吧,翻了一下,還了解到,這個機制是仿照MAC OS里面launchd來的。貌似是個比較復雜的話題,那就改天再深入研究吧。

 

參考文檔:

1、ubuntu bootup howto,https://help.ubuntu.com/community/UbuntuBootupHowto

2、inittab,http://pic.dhe.ibm.com/infocenter/aix/v7r1/index.jsp?topic=%2Fcom.ibm.aix.files%2Fdoc%2Faixfiles%2Finittab.htm

3、systemd,http://freedesktop.org/wiki/Software/systemd/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM