
Linux系統的快速初始化。 Claudio Matsuoka從Eeepc FastInit進行了反向設計 - “充滿青蛙DNA的差距……”

圖1:有限引導Alpine Linux(HowTO)的屏幕截圖。
功能包括:
/etc/rc.local支持/etc/network/interfacesinitctl top中的配置和監視sulogin的適當救援模式,用於受保護的維護外殼syslogd啟動之前,登錄到內核環緩衝區,請參閱推薦的Sysklogd項目,以完成日誌記錄集成以及如何使用logger從腳本中登錄到內核環緩衝區專注於小型和嵌入式系統,儘管在服務器和桌面系統上也完全可以使用。有關工作的示例,請參閱帶有以下Linux分佈的教程的貢獻/部分:
注意:對各種Linux發行版的支持並不意味著所有架構都可以輕鬆安裝。捆綁的安裝腳本是標準安裝的示例,在AMD64(X86_64)系統上測試。自定義設置(例如,用於嵌入式系統)可以在以下任何基於構建根的示例中找到:Mylinux,Infix或Plain Br2-Finit-Demo。
此示例/etc/finit.conf也可以在/etc/finit.d中的多個.conf文件中拆分。可用但尚未啟用,可以將服務放置在/etc/finit.d/available中,並由運營商使用Initctl工具啟用。請參閱上述Linux發行版或Mylinux。
注意:從有限的v4.4開始,可以使用標準UNIX持續字符(
)分解.conf行,現在也支持尾隨註釋。後者意味著您需要逃避指令和描述(#)中使用的任何哈希。有關此信息和示例的更多信息,請參見finit.conf(5)手冊或doc/config.md。
# Fallback if /etc/hostname is missing
host default
# Runlevel to start after bootstrap, 'S', default: 2
# runlevel 2
# Support for setting global environment variables, using foo=bar syntax
# be careful though with variables like PATH, SHELL, LOGNAME, etc.
# PATH=/usr/bin:/bin:/usr/sbin:/sbin
# Max file size for each log file: 100 kiB, rotate max 4 copies:
# log => log.1 => log.2.gz => log.3.gz => log.4.gz
log size=100k count=4
# Services to be monitored and respawned as needed
service [S12345] env:-/etc/conf.d/watchdog watchdog $WATCHDOG_OPTS $WATCHDOG_DEV -- System watchdog daemon
service [S12345] env:-/etc/conf.d/syslog syslogd -n $SYSLOGD_OPTS -- System log daemon
service [S12345] < pid /syslogd> env:-/etc/conf.d/klogd klogd -n $KLOGD_OPTS -- Kernel log daemon
service [2345] env:-/etc/conf.d/lldpd lldpd -d $LLDPD_OPTS -- LLDP daemon (IEEE 802.1ab)
# The BusyBox ntpd does not use syslog when running in the foreground
# So we use this trick to redirect stdout/stderr to a log file. The
# log file is rotated with the above settings. The condition declares
# a dependency on a system default route (gateway) to be set. A single
# <!> at the beginning means ntpd does not respect SIGHUP for restart.
service [2345] log:/var/log/ntpd.log <!net/route/default> ntpd -n -l -I eth0 -- NTP daemon
# For multiple instances of the same service, add :ID somewhere between
# the service/run/task keyword and the command.
service :80 [2345] merecat -n -p 80 /var/www -- Web server
service :8080 [2345] merecat -n -p 8080 /var/www -- Old web server
# Alternative method instead of below runparts, can also use /etc/rc.local
# sysv [S] /etc/init.d/keyboard-setup -- Setting up preliminary keymap
# sysv [S] /etc/init.d/acpid -- Starting ACPI Daemon
# task [S] /etc/init.d/kbd -- Preparing console
# Hidden from boot progress, using empty `--` description
# sysv [S] /etc/init.d/keyboard-setup --
# sysv [S] /etc/init.d/acpid --
# task [S] /etc/init.d/kbd --
# Run start scripts from this directory
# runparts /etc/start.d
# Virtual consoles run BusyBox getty, keep kernel default speed
tty [12345] /sbin/getty -L 0 /dev/tty1 linux nowait noclear
tty [2345] /sbin/getty -L 0 /dev/tty2 linux nowait noclear
tty [2345] /sbin/getty -L 0 /dev/tty3 linux nowait noclear
# Use built-in getty for serial port and USB serial
# tty [12345] /dev/ttyAMA0 noclear nowait
# tty [12345] /dev/ttyUSB0 noclear
# Just give me a shell, I need to debug this embedded system!
# tty [12345] console noclear nologin service節以及task run和其他任務都在Doc/Config.md中全面描述。這是啟動Unix守護程序所需的一些最常見組件的快速概述:
service [LVLS] <COND> log env:[-]/etc/default/daemon daemon ARGS -- Daemon daemon
^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | `---------- Optional description
| | | | | | `------------------ Daemon arguments
| | | | | `------------------------- Path to daemon
| | | | `---------------------------------------------------- Optional env. file
| | | `-------------------------------------------------------- Redirect output to log
| | `--------------------------------------------------------------- Optional conditions
| `---------------------------------------------------------------------- Optional Runlevels
`------------------------------------------------------------------------------ Monitored application
一些組件是可選的:runlevel(s),條件(S)和描述,使創建簡單的啟動腳本變得容易,並且對於更高級的用途也很可能:
service /usr/sbin/sshd -D
使用條件處理依賴項。最常見的條件之一是等待基本網絡可用:
service <net/route/default> nginx -- High performance HTTP server
這是另一個示例,我們指示有限在syslogd正常啟動之前不要啟動busybox ntpd 。有限等待syslogd創建其PID文件,默認情況下/var/run/syslogd.pid 。
service [2345] log <!pid/syslogd> ntpd -n -N -p pool.ntp.org
service [S12345] syslogd -n -- Syslog daemon
請注意log關鍵字,BusyBox ntpd使用stderr在前景中運行時記錄。使用log Finit將stdout + stderr重定向到系統日誌守護程序,使用命令行logger(1)工具。
服務或任務可以列出多個依賴項。在這裡,我們等待兩個syslogd啟動並基本網絡啟動:
service [2345] log <pid/syslogd,net/route/default> ntpd -n -N -p pool.ntp.org
如果兩種條件失敗,例如網絡丟失, ntpd會停止,並且一旦再次恢復, ntpd就會自動重新啟動。
注意:確保守護程序不會像上面的openssh一樣,不朝著控制tty(通常是-n或-f標誌)或-D分離。如果它自行拆下,則無法監視它,而是嘗試重新啟動它。
過程監督
如果他們失敗,請開始,監視和重新啟動服務。
蓋蒂
有限支持外部蓋蒂,但還具有有限的內置蓋蒂,對非常小的系統有用。蓋蒂(Getty)設置了TTY並等待用戶輸入,然後再移交給/bin/login ,該bin /login負責處理實際的身份驗證。
tty [12345] /dev/tty1 nowait linux
tty [12345] /dev/ttyAMA0 noclear vt100
tty [12345] /sbin/getty -L /dev/ttyAMA0 vt100
嵌入式系統的用戶可能需要使用特殊@console設備啟用自動串行控制台。無論天氣如何,系統都使用ttyS0 , ttyAMA0 , ttyMXC0或其他任何東西。通過查詢sysfs: /sys/class/tty/console/active來確定它。
tty [12345] @console linux noclear
請注意,可選的noclear , nowait和nologin Flags。後者是為了完全跳過登錄過程。有關更多信息,請參見Doc/config.md。
跑步
可以提供對SYSV Init-style runlevels的支持,其最小風格與有限的其他所有內容相同。 [2345]語法可以應用於服務,任務,運行和TTY stanzas。
保留的跑步分別為0和6,停止和重新啟動,就像SYSV Init一樣。可以自由配置runlevel 1,但建議保留為系統單用戶runlevel,因為有限不會在此處啟動網絡。從/etc/finit.conf中配置的runlevel NUM是Bootstrap之後的有限更改,除非在內核CMDLine上給出“單個”(或“ S”),在這種情況下,啟動了Runlevel 1。
Runlevel S中的所有服務首先啟動,其次是所需的Run Time Runlevel。可以使用run [S] cmd在Runlevel S中的運行任務序列。在運行時更改運行時,就像其他任何初始化一樣,例如INIT 4 ,也使用更高級的intictl工具。
狀況
如前所述,FITIT具有處理同步的高級依賴系統,稱為條件。它可以通過多種方式使用;取決於另一個服務,網絡可用性等。
對於嵌入式系統來說,一個非常酷的示例是,如果板在其設備樹中編碼某些功能,則運行某些腳本。在Bootstrap,我們運行以下ident腳本:
#! /bin/sh
conddir=/var/run/finit/cond/hw/model
dtmodel=/sys/firmware/devicetree/base/model
if ! test -e $dtmodel ; then
exit 0
fi
model= $( cat $dtmodel | tr " [A-Z] " " [a-z]- " )
mkdir -p $conddir && ln -s ../../reconf $conddir / $model如果存在設備樹節點並且是字符串,則在啟動其他腳本時,我們可以使用條件<hw/model/foo> 。這是一個示例:
run [S] /path/to/ident --
task [2] <hw/model/foo> /path/to/foo-init -- Initializing Foo board
請注意用空描述的技巧,以隱藏對
ident的調用,以限制進度輸出。
插件
插件可以將有限和鉤子的功能擴展到引導過程的不同階段和運行時。插件用C編寫,並將其編譯到動態庫中,該庫會自動通過啟動時自動加載。一組基本的插件在plugins/目錄中捆綁在一起。
功能:
擴展和功能與/sbin/init啟動系統所需的內容無關緊要,該系統可作為一組插件可用,該插件將插入引導過程或響應各種I/O。
有關更多信息,請參見Doc/plugins.md。
自動重新加載
默認情況下,fitit monitors /etc/finit.d/和/etc/finit.d/enabled/註冊.conf文件的任何更改。要激活一個更改,用戶必須調用initctl reload ,該更改將重新加載所有修改的文件,停止所有刪除服務,啟動新的服務並重新啟動任何修改後的服務。如果服務的命令行參數已更改,則該過程將終止,然後從更新的參數開始。如果尚未修改參數,並且該過程支持嘆息,則該過程將獲得嘆息而不是終止並開始。
對於某些用例,調用initctl reload的額外步驟會創建一個不必要的開銷,可以在構建時間使用以下方式刪除:
configure --enable-auto-reload
cgroups
FITIT支持Cgroups V2,並帶有以下默認組,其中服務和用戶會話放在:
/sys/fs/cgroup
|-- init/ # cpu.weight:100
|-- system/ # cpu.weight:9800
`-- user/ # cpu.weight:100
有限的本身及其輔助腳本和服務放置在頂級葉節組init/中,這也是保留的。
所有運行/任務/服務/SYSV流程都放在system/中的子組中。每個子組的名稱取自/etc/finit.d的相應.conf文件。
所有蓋蒂/ TTY過程都放在自己的user/中的子組中。每個子組的名稱取自用戶名。
也存在第四組, root組。它也是保留的,主要用於RT任務。如果您有RT任務,則需要在他們的服務節中宣布這樣的聲明:
service [...] <...> cgroup.root /path/to/foo args -- description
或者
cgroup.root
service [...] <...> /path/to/foo args -- description
service [...] <...> /path/to/bar args -- description
有關更多信息,例如,如何配置每組限制,請參見Doc/Config.md。
initctl工具具有三個命令,可以幫助調試和優化CGROUP的設置和監視。有關詳細信息,請參見ps , top和cgroup命令。
注意:不支持CGROUP,特別是版本2的系統將自動檢測到。在此類系統上,以上功能在啟動時會儘早禁用。
在啟動結束時,當所有Bootstrap( S )任務和服務都啟動但沒有網絡時,有限的命令在任何配置的runparts <DIR> Directory上呼叫其內置的運行parts(8)命令。在更改為配置的Runlevel(默認2)之前,這會發生。 (在從單用戶模式更改之前,啟用了網絡。)
runparts /etc/rc.d/在所有服務啟動時,runlevel更改後, /etc/rc.local被調用。
rc.local不需要/etc/finit.conf中的配置節。如果它存在並且是可執行的shell腳本,則在調用HOOK_SYSTEM_UP之前,在啟動的末尾將其調用。在Doc/插件中查看有關掛鉤的更多信息。
不可能通過信號調用finit或在任何runparts或/etc/rc.local腳本中使用initctl 。這是因為有限是單線線,並且在Runlevel s結束時以阻止方式調用這些腳本,此時,事件循環尚未啟動。
事件循環是圍繞有限的整個過程,除了runlevel s外,它在許多設置中仍然是一個緩慢的遊行,並帶有一些鉤子,並在外部腳本上封鎖了呼叫。
但是,並非所有initctl命令都被禁止。支持命令:
inictl cond :僅在/run/finit/cond操作文件initctl enable/disable :啟用run/task/service在從s到2的runlevel更改上激活initctl touch/show/create/delete/list : create ,只要使用非相互作用模式,請在Bootstrap之後直接在Runlevel更改中進行更改initctl -f reboot/poweroff/halt :提供-f標誌用於強制直接內核命令示例:您可以在/etc/rc.local中設置usr/條件,並在Runlevel 2中具有服務/任務取決於其執行。
v1.8的Finit中包括對Runlevels的基本支持。默認情況下,列出的所有服務,任務,運行命令和TTY,而沒有一組runlevels獲取默認設置[234] 。啟動後的默認運行級別為2。
FITIT支持Runlevels 0-9,並且S為Halt保留0,6重新啟動和S僅在Bootstrap上運行。 Runlevel 1是單個用戶級別,通常不啟用網絡。在有限的情況下,這更多是用戶定義的策略。通常,僅使用runlevels 1-6,甚至更常見的是,僅使用默認的runlevel。
要為service , run命令, task或tty指定一組允許的運行級別,請將[NNN]添加到您的/etc/finit.conf ,如下:
service [S12345] syslogd -n -x -- System log daemon
run [S] /etc/init.d/acpid start -- Starting ACPI Daemon
task [S] /etc/init.d/kbd start -- Preparing console
service [S12345] <pid/syslogd> klogd -n -x -- Kernel log daemon
tty [12345] /dev/tty1
tty [2] /dev/tty2
tty [2] /dev/tty3
tty [2] /dev/tty4
tty [2] /dev/tty5
tty [2] /dev/tty6
在此示例中,Syslogd首先並行啟動,然後使用常規的SYSV INIT腳本來調用ACPID。它使用運行命令調用,這意味著以下任務命令啟動KBD腳本直到ACPID Init腳本完全完成後才調用。然後,鍵盤設置腳本與KloGD並行稱為監視服務。
同樣,任務和服務是並行啟動的,而在列出的順序中調用運行命令,並且直到運行命令完成後才啟動後續命令。此外,任務和運行命令是在外殼中運行的,因此可以使用管道和重定向。
以下示例說明了這一點。引導程序任務和運行命令在完成後也將刪除, initctl show不會列出它們。
task [S] echo "foo" | cat >/tmp/bar
run [S] echo "$HOME" >/tmp/secret
可以通過使用單個參數(例如init 5或使用initctl runlevel 5 )調用INIT在runlevels之間進行切換,均可以切換到Runlevel 5。更改Runlevels時,有限也會自動重新加載所有.conf Files中的所有/etc/finit.d/文件。因此,如果您想設置新的系統配置,請切換到Runlevel 1,更改系統中的所有配置文件,然後在/etc/finit.d中觸摸所有.conf文件,然後再切換回上一個Runlevel,然後再次切換到上一個Runlevel-此方式既可以停止舊服務又可以為您啟動任何新服務,而無需重新啟動系統。
傳統上,重新啟動和停止UNIX系統是通過更改其跑步來完成的。有限提供其自己的工具提供: shutdown , reboot , poweroff和suspend ,以及下一節中詳細介紹的initctl工具。
出於兼容原因,有限的原因是聆聽與Busybox Init相同的信號集。這與SYSV Init不兼容100%,但顯然是更常見的組合。有關更多詳細信息,請參見DOC/SIGNALS.MD。
有限還將現代API實現以查詢狀態,並開始/停止服務,稱為initctl 。與telinit不同,在給定命令完全完成之前, initctl工具不會返回。
Usage: initctl [OPTIONS] [COMMAND]
Options:
-b, --batch Batch mode, no screen size probing
-c, --create Create missing paths (and files) as needed
-f, --force Ignore missing files and arguments, never prompt
-h, --help This help text
-j, --json JSON output in 'status' and 'cond' commands
-1, --once Only one lap in commands like 'top'
-p, --plain Use plain table headings, no ctrl chars
-q, --quiet Silent, only return status of command
-t, --no-heading Skip table headings
-v, --verbose Verbose output
-V, --version Show program version
Commands:
debug Toggle Finit (daemon) debug
help This help text
version Show program version
ls | list List all .conf in /etc/finit.d
create <CONF> Create .conf in /etc/finit.d/available
delete <CONF> Delete .conf in /etc/finit.d/available
show <CONF> Show .conf in /etc/finit.d/available
edit <CONF> Edit .conf in /etc/finit.d/available
touch <CONF> Change .conf in /etc/finit.d/available
enable <CONF> Enable .conf in /etc/finit.d/available
disable <CONF> Disable .conf in /etc/finit.d/enabled
reload Reload *.conf in /etc/finit.d (activate changes)
cond set <COND> Set (assert) user-defined conditions +usr/COND
cond get <COND> Get status of user-defined condition, see $? and -v
cond clear <COND> Clear (deassert) user-defined conditions -usr/COND
cond status Show condition status, default cond command
cond dump [TYPE] Dump all, or a type of, conditions and their status
log [NAME] Show ten last Finit, or NAME, messages from syslog
start <NAME>[:ID] Start service by name, with optional ID
stop <NAME>[:ID] Stop/Pause a running service by name
reload <NAME>[:ID] Reload service as if .conf changed (SIGHUP or restart)
This allows restart of run/tasks that have already run
Note: Finit .conf file(s) are *not* reloaded!
restart <NAME>[:ID] Restart (stop/start) service by name
signal <NAME>[:ID] <S> Send signal S to service by name, with optional ID
ident [NAME] Show matching identities for NAME, or all
status <NAME>[:ID] Show service status, by name
status Show status of services, default command
cgroup List cgroup config overview
ps List processes based on cgroups
top Show top-like listing based on cgroups
plugins List installed plugins
runlevel [0-9] Show or set runlevel: 0 halt, 6 reboot
reboot Reboot system
halt Halt system
poweroff Halt and power off system
suspend Suspend system
utmp show Raw dump of UTMP/WTMP db
對於不支持SIGHUP服務,必須使用.conf文件中的<!>表示法來告訴Finit,以停止並在reload和runlevel更改上啟動它。如果<>持有更多條件,這些條件也會影響維持服務的方式。
注意:即使有可能啟動不屬於當前運行時的服務,如果它們退出(崩潰),這些服務也不會自動重新出現。因此,如果跑步級為2,則下面的dropbear SSH服務如果被殺死或退出,則不會重新啟動。
status命令是默認值,它顯示了所有監視運行/任務/服務的快速概述。在這裡,我們稱為initctl -p ,適用於腳本和文檔:
alpine:~# initctl -p
PID IDENT STATUS RUNLEVELS DESCRIPTION
======================================================================
1506 acpid running [---2345----] ACPI daemon
1509 crond running [---2345----] Cron daemon
1489 dropbear running [---2345----] Dropbear SSH daemon
1511 klogd running [S-12345----] Kernel log daemon
1512 ntpd running [---2345----] NTP daemon
1473 syslogd running [S-12345----] Syslog daemon
alpine:~# initctl -pv
PID IDENT STATUS RUNLEVELS COMMAND
======================================================================
1506 acpid running [---2345----] acpid -f
1509 crond running [---2345----] crond -f -S $CRON_OPTS
1489 dropbear running [---2345----] dropbear -R -F $DROPBEAR_OPTS
1511 klogd running [S-12345----] klogd -n $KLOGD_OPTS
1512 ntpd running [---2345----] ntpd -n $NTPD_OPTS
1473 syslogd running [S-12345----] syslogd -n
對於Alpine Linux, /etc/conf.d/ conf.d/讀取了上述每個服務的環境變量。其他分佈可能具有其他目錄,例如,debian使用/etc/default/ 。
status命令採用可選NAME:ID參數。在這裡,我們檢查了dropbear的狀態,該系統在此系統中只有一個實例:
alpine:~# initctl -p status dropbear
Status : running
Identity : dropbear
Description : Dropbear SSH daemon
Origin : /etc/finit.d/enabled/dropbear.conf
Environment : -/etc/conf.d/dropbear
Condition(s):
Command : dropbear -R -F $DROPBEAR_OPTS
PID file : !/run/dropbear.pid
PID : 1485
User : root
Group : root
Uptime : 2 hour 46 min 56 sec
Runlevels : [---2345----]
Memory : 1.2M
CGroup : /system/dropbear cpu 0 [100, max] mem [--.--, max]
|- 1485 dropbear -R -F
|- 2634 dropbear -R -F
|- 2635 ash
`- 2652 initctl -p status dropbear
Apr 8 12:19:49 alpine authpriv.info dropbear[1485]: Not backgrounding
Apr 8 12:37:45 alpine authpriv.info dropbear[2300]: Child connection from 192.168.121.1:47834
Apr 8 12:37:46 alpine authpriv.notice dropbear[2300]: Password auth succeeded for 'root' from 192.168.121.1:47834
Apr 8 12:37:46 alpine authpriv.info dropbear[2300]: Exit (root) from <192.168.121.1:47834>: Disconnect received
Apr 8 15:02:11 alpine authpriv.info dropbear[2634]: Child connection from 192.168.121.1:48576
Apr 8 15:02:12 alpine authpriv.notice dropbear[2634]: Password auth succeeded for 'root' from 192.168.121.1:48576
FITIT能夠在帶有UDEV和嵌入式系統的兩個桌面/服務器系統上運行,通常隨附BusyBox MDEV。某些系統今天具有SystemD-udeV或EudeV,而不是原始的UDEV,在運行時對所有系統的所有探針都有限,並且期望/dev/是使用devtmpfs的可寫文件系統。如果需要,也可以在靜態設置/dev運行。但是,同時安裝UDEV和MDEV並不是一個好主意,這將導致無法預測的結果。
在BOOT FITIT調用mdev或udevd以填充/dev情況下,這是略有不同的,在使用UDEV的系統上,您可能需要在/etc/finit.conf中添加以下單發任務:
run [S] udevadm settle --timeout=120 -- Waiting for udev
FITIT具有內置的TTY Getty,但需要工作/bin/login或/bin/sh ,如果沒有在/etc/finit.conf中配置tty。
對於完全操作的系統/var , /run和/tmp必須在/etc/fstab中正確設置,該設置在啟動時迭代。
該項目基於Claudio Matsuoka的原始有限,該項目是根據Eeepc Fastinit的Syscall進行了反向設計的 - “充滿青蛙DNA的間隙……”
有限是由Joachim Wiberg在Github開發和維護的。請提交錯誤報告,克隆它或發送“錯誤修復”和“提議擴展”請求。