लिनक्स बूट कैसे करता है

अपडेट: मार्च 2013 में लेख और लिपियों को अपडेट किया गया था (5 साल बीत चुके हैं, पुरानी स्क्रिप्ट वर्तमान से बहुत भिन्न नहीं हैं, लेकिन वर्तमान कोड का अध्ययन करना बेहतर है, और सिस्टम बूट तर्क पिछले कुछ वर्षों में बदल गया है - अन्यथा udv काम करता है, नया सिंथेटिक एफएस दिखाई दिया है) जैसे devtmpfs, /var/run स्थानांतरित /run to /run , etc)।

जब मैंने लिनक्स में महारत हासिल की, तो मुझे बहुत दिलचस्पी थी कि सिस्टम बूट होने पर क्या होता है। बूट प्रक्रिया को समझने की कोशिश ने मुझे बूट स्क्रिप्ट ( /etc/inittab, /etc/rc*, /etc/init.d/*, ... ) और उनके कॉन्‍फ़िगरेशन ( /etc/sysconfig/*, /etc/cond.f/*, ... ) के स्रोतों तक /etc/inittab, /etc/rc*, /etc/init.d/*, ... /etc/sysconfig/*, /etc/cond.f/*, ... )। यह इन लिपियों के गंभीर आकार और जटिलता को ध्यान देने योग्य है - उन्हें पता लगाने में बहुत समय लगा। लेकिन उन दिनों में, मुझे पूरा विश्वास था कि डाउनलोड करना एक जटिल प्रक्रिया थी, और बूट स्क्रिप्ट के आकार और जटिलता को उचित ठहराया गया था।

जब रेडहैट को आखिरकार मुझे (2001) मिला, तो मैंने अपना एलएफएस आधारित वितरण बनाने का फैसला किया। मेरे वितरण के लिए मुझे स्वयं बूट स्क्रिप्ट विकसित करनी पड़ी, और फिर सच्चाई स्पष्ट हो गई: बूट प्रक्रिया में कुछ भी जटिल नहीं है!

अपने वितरण (PoWeR लिनक्स) पर 2.5 साल तक काम करने के बाद, मैं Gentoo में चला गया (मेरे पास गुणवत्ता के लिए पर्याप्त समय नहीं था)। जेंटू बूट स्क्रिप्ट सीखने के बाद, मैं भयभीत था! उनका आकार और जटिलता पुराने रेडहैट से भी अधिक थी। एक विस्तृत अध्ययन के बाद, कारण स्पष्ट हो गया: बूट स्क्रिप्ट का एक ही सेट लाइवसीडी और नियमित प्रणाली दोनों के लिए उपयोग किया गया था - इस तरह के एक सार्वभौमिक राक्षस। इसलिए जब मैंने Gentoo पर स्विच किया, तो मैंने PoWeR लिनक्स से बूट स्क्रिप्ट लेने का फैसला किया और मानक Gentoo वाले का उपयोग नहीं किया (यानी, मैं केवल Gentoo से पोर्टेज का उपयोग करता हूं)। और तब से, 4 और वर्षों के लिए, ये स्क्रिप्ट मेरे होम वर्कस्टेशन और रिमोट सर्वर के एक समूह पर काम कर रही है।

की विशेषताओं


लिपियों का आकार (सभी एक साथ) 308 रेखाएँ, 8KB:
 $ wc 1 3 lib.sh 201 769 5855 1 78 272 1726 3 29 118 771 lib.sh 308 1159 8352  

विपक्ष:
  1. सभी एक फ़ाइल में - अनुप्रयोगों को अपडेट करते समय इस एप्लिकेशन के प्रारंभ कोड को स्वचालित रूप से अपडेट करना लगभग असंभव है। उदाहरण के लिए, जब ALSA अपडेट किया जाता है, तो पैकेज केवल /etc/init.d/alsasound, /etc/conf.d/alsasound, /etc/modules.d/alsa फ़ाइलों को बदल सकता है। और मेरे मामले में, व्यवस्थापक को पेन के /etc/runit/1 को संपादित करने की आवश्यकता होगी।
  2. दुनिया में हर चीज का कोई समर्थन नहीं है। उदाहरण के लिए, मैं RAID और LVM का उपयोग नहीं करता हूं - इसलिए आपको उन्हें स्वयं प्रारंभ करने के लिए कमांड जोड़ने की आवश्यकता होगी।
  3. आपको इन लिपियों का स्वतंत्र रूप से समर्थन करने की आवश्यकता होगी। Gentoo को अपडेट करते समय, मैं आमतौर पर (अप्रयुक्त) /etc/init.d/* स्क्रिप्ट में परिवर्तन देखता हूं और यदि कुछ महत्वपूर्ण परिवर्तन होता है, तो मैं अपनी स्क्रिप्ट को अपडेट करता हूं। लेकिन, व्यवहार में, इस तरह के परिवर्तनों की आवश्यकता लगभग हर दो साल में उठती है।

पेशेवरों:
  1. सभी एक छोटी फ़ाइल में - स्क्रिप्ट और उनके कॉन्फ़िगरेशन के लिए एक गुच्छा देखने की आवश्यकता नहीं है जहां आप कॉन्फ़िगर करते हैं कि आपको क्या चाहिए; आप सिस्टम की सभी बुनियादी सेटिंग्स को जल्दी और आसानी से देख सकते हैं।
  2. घरेलू कंप्यूटर और सर्वर पर 11.5 साल तक मुझे और मेरे दोस्तों की जरूरत की हर चीज का समर्थन है।
  3. लिनक्स आरंभीकरण प्रक्रिया की खोज के लिए आदर्श। आप वास्तविक बुनियादी लिनक्स कमांड के साथ काम करते हैं, जो सभी वितरणों में समान हैं, और स्क्रिप्ट के साथ नहीं और आपके वितरण के लिए विशिष्ट कॉन्फ़िगर करता है।
  4. सिस्टम लोडिंग को गति दें। मेरी घरेलू मशीन 11 सेकंड में सिंगल यूजर मोड (गेटी, सिसलॉग, क्लॉज, एकपीड, डेंस्कैचे, टिनिडन, जीपीएम) के साथ 6 कंसोल में लोड होती है। मैंने इनिटंग शैली में समानांतर लोडिंग के साथ प्रयोग किया - लिपियों की जटिलता और अनावश्यक प्रक्रियाओं की पीढ़ी के कारण प्रभाव बल्कि नकारात्मक है। Initng पारंपरिक, ब्लोटेड लिपियों की लोडिंग को तेज करने के लिए अच्छा है जो कई अनावश्यक क्रियाओं को करते हैं, और मेरे मामले में तेजी लाने के लिए कुछ भी नहीं है। :)

छोटे आकार के बावजूद, ये स्क्रिप्ट न केवल मज़बूती से और जल्दी से सिस्टम को लोड करते हैं, बल्कि कई विशेषताओं का भी समर्थन करते हैं जो व्यवस्थापक के जीवन को आसान बनाते हैं:


बूट पर प्रदर्शित संदेशों का उदाहरण


+ UDEV
+ मॉड्यूल
+ SYSCTL
+ MTAB
- माउंट

++ स्वपन-ए
++ गलत
बाहर निकलें कोड: 1
++ माउंट-नाटोका, नोनफ्स, नोप्रोक्स, नॉनकॉफ्स, नोसंबफ्स, नोशम
... खोल खोलने के लिए 5 सेकंड में किसी भी कुंजी को दबाएं ...
+ CLEANTMP
+ RANDOMSEED
+ HWCLOCK
+ सेंसर
+ LOADKEYS
+ ध्वनि
+ HOST_NAME
+ उन्नत करें
+ नेटवर्क
+ रन
+ DMESG



RUNIT


SysVinit के बजाय, मैं Runit से बूट करने के लिए उपयोग करता हूं । रनिट /etc/inittab समर्थन नहीं करता है, इसके बजाय, यह एक सरल योजना का उपयोग करता है:
  1. लोड करते समय, स्क्रिप्ट /etc/runit/1 । उनका कार्य प्रणाली को पूरी तरह से शुरू करना है।
  2. स्क्रिप्ट /etc/runit/1 पूरा होने पर, स्क्रिप्ट /etc/runit/2 लॉन्च किया जाता है, जिसे सभी आवश्यक सेवाओं (syslog, getty, ssh, apache, ...) को चलाना चाहिए।
  3. जब उपयोगकर्ता सिस्टम को बंद / रिबूट करता है, तो स्क्रिप्ट /etc/runit/3 जिसे शटडाउन के लिए सिस्टम तैयार करना चाहिए (सभी प्रक्रियाओं को समाप्त करें, अनमाउंट डिस्क, आदि)।

यदि वांछित है, तो आप उसी शैली में काम करने के लिए SysVinit को कॉन्फ़िगर कर सकते हैं:

SysVinit से रनिंग / etc / runit / {1,2,3}: / etc / inittab


आईडी: 3: initdefault:
rc :: bootwait: / etc / runit / 1
l0: 0: Wait: / bin / sh -c '/ etc / runit / 3; निष्पादित / sbin / पड़ाव '
l3: 3: एक बार: / etc / runit / 2
l6: 6: प्रतीक्षा करें: / बिन / श-सी '/ आदि / रनिट / 3; निष्पादित / sbin / रिबूट '
ca: 12345: ctrlaltdel: / sbin / shutdown -r अब


सेवाएं


सभी सेवाओं को शुरू करने के लिए (getty, syslog, mysql, आदि) मैं एक ही रनिट का उपयोग करता हूं (वास्तव में, यह डेमोंटोलस का सिर्फ थोड़ा बेहतर संस्करण है)। लेकिन यह एक अलग विषय है, इसलिए मैं स्पष्ट करूंगा कि इस लेख में सेवाओं को लॉन्च करने के लिए कोई स्क्रिप्ट नहीं है, केवल सिस्टम का इनिशियलाइज़ेशन / शटडाउन है।

स्रोत कोड


सहायक कार्य: /etc/runit/lib.sh


 #!/bin/bash startlog() { exec 3>&1 4>&2 1> >(tee $1) 2>&1; } stoplog() { exec 1>&3- 2>&4-; } wanna() { echo -e "\a... press any key in $2 seconds to $1 ..." read -t $2 -n 1 -s </dev/console } emergency() { if wanna "open shell" 5; then bash --norc </dev/console &>/dev/console if [[ "$0" == "/etc/runit/1" ]] && wanna "reboot now" 3; then exit 100 fi fi } trace() { trap 'ERR=$?' ERR; set -Ex; $1 2>&1; set +Ex; trap ERR; } 2>&- try() { local output=$( trace $1 ) if [[ "$output" =~ "ERR=" ]]; then echo -e "\e[1m\e[31m - \e[37m$1\e[0m" echo "$output" | sed $'s/.*ERR=\(.*\)/\a\033[36mEXIT CODE: \\1\033[0m/g' emergency else echo -e "\e[1m\e[32m + \e[37m$1\e[0m" fi } 


Startup: / etc / runit / 1


 #!/bin/bash CONSOLE() { dmesg -n 1 } INIT() { mount -n -t proc -o "noexec,nosuid,nodev" none /proc mount -n -t sysfs -o "noexec,nosuid,nodev" none /sys mount -n -t tmpfs -o "mode=0755,nosuid,nodev" none /run mkdir /run/lock chmod 0775 /run/lock chown root:uucp /run/lock if grep -qs devtmpfs /proc/mounts; then mount -n -t devtmpfs -o "remount,exec,nosuid,mode=0755,size=10M" none /dev elif grep -qs devtmpfs /proc/filesystems; then mount -n -t devtmpfs -o "exec,nosuid,mode=0755,size=10M" none /dev else mount -n -t tmpfs none /dev busybox mdev -s fi # needed to run startlog (in /etc/runit/lib.sh) before UDEV ln -snf /proc/self/fd /dev/fd # extra mountpoints in /dev mkdir -p /dev/pts mount -n -t devpts -o "noexec,nosuid,gid=5,mode=0620" none /dev/pts mkdir -p /dev/shm mount -n -t tmpfs -o "noexec,nosuid,nodev" none /dev/shm } UDEV() { echo "" >/proc/sys/kernel/hotplug udevd --daemon udevadm trigger --type=subsystems --action=add udevadm trigger --type=devices --action=add udevadm settle --timeout=30 } HWCLOCK() { hwclock --hctosys --localtime && touch /run/init.hwclock } MODULES() { true # bash doesn't allow empty functions # modprobe -q nvidia NVreg_DeviceFileMode=432 NVreg_DeviceFileUID=0 NVreg_DeviceFileGID=27 NVreg_ModifyDeviceFiles=1 # modprobe -q -a vmmon vmci vsock vmblock vmnet # modprobe -q -a vboxdrv vboxnetflt vboxnetadp } FSCK() { fsck -A -p -C0 -T -t noafs,nocifs,nocoda,nodavfs,nofuse,nofuse.sshfs,nogfs,noglusterfs,nolustre,noncpfs,nonfs,nonfs4,noocfs2,noshfs,nosmbfs,noopts=_netdev } REMOUNT() { mount -n -o remount,rw / grep -v ^rootfs /proc/mounts > /etc/mtab for i in $(cut -d ' ' -f 2 /etc/mtab | grep -vx /); do mount -o remount "$i" done } LOCALMOUNT() { mount -at noproc,noafs,nocifs,nocoda,nodavfs,nofuse,nofuse.sshfs,nogfs,noglusterfs,nolustre,noncpfs,nonfs,nonfs4,noocfs2,noshfs,nosmbfs -O no_netdev swapon -a } SYSCTL() { sysctl -p /etc/sysctl.conf } MIGRATERUN() { rm -rf /var/lock ln -s /run/lock /var/lock rm -rf /var/run ln -s /run /var/run } UTMPWTMP() { > /var/run/utmp chgrp utmp /var/run/utmp chmod 0664 /var/run/utmp [ -e /var/log/wtmp ] || cp -a /var/run/utmp /var/log/wtmp } CLEANTMP() { rm -f /tmp/.X*-lock /tmp/esrv* /tmp/kio* /tmp/jpsock.* /tmp/.fam* rm -rf /tmp/.esd* /tmp/orbit-* /tmp/ssh-* /tmp/ksocket-* /tmp/.*-unix mkdir -p /tmp/.{ICE,X11}-unix chmod 1777 /tmp/.{ICE,X11}-unix } RANDOMSEED() { mkdir -p /var/lib/misc [ -f /var/lib/misc/random-seed ] && cat /var/lib/misc/random-seed >/dev/urandom rm -f /var/lib/misc/random-seed local psz=$(( $(sysctl -n kernel.random.poolsize 2>/dev/null || echo 4096) / 4096 )) (umask 077; dd if=/dev/urandom of=/var/lib/misc/random-seed count=$psz 2>/dev/null) } SENSORS() { sensors -s } LOADKEYS() { # Commands for TTY initialization like 'setfont' and 'echo -ne "\033(K"' # shouldn't be executed in /etc/runit/1 because: # - which TTYs should be initialized may depend on current runlevel # - if TTY state become broken (for ex. after 'cat /dev/urandom'), # then after logout and login TTY state should be reinitialized # these commands should be executed before each getty invocation instead. kbd_mode -u loadkeys koi2 # -q windowkeys # loadkeys -q -u ru4 dumpkeys -c koi8-r | loadkeys --unicode } SOUND() { alsactl -f /etc/asound.state restore && touch /run/init.alsa } HOST_NAME() { # Here you should set only "host" part of your fqdn. # Add this line to /etc/hosts to configure FQDN: # YOUR.IP.ADDR.ESS YOUR_HOSTNAME.DOMAIN.TLD YOUR_HOSTNAME hostname YOUR_HOSTNAME } NETWORK() { ip link set lo up iptables-restore </etc/iptables #ip link set eth0 up #ip addr add 192.168.1.2/24 dev eth0 #ip route add default via 192.168.1.1 dev eth0 } RUNIT() { # Set default action (shutdown or not) if Ctrl+Alt+Del pressed, # but /etc/runit/ctrlaltdel don't setup /etc/runit/stopit. touch /etc/runit/stopit chmod 100 /etc/runit/stopit # Set default action on shutdown (halt or reboot) if: # - /etc/runit/1 crash or exit 100 # - /etc/runit/2 exit non 111 # - Ctrl+Alt+Del pressed, but /etc/runit/ctrlaltdel don't setup /etc/runit/reboot touch /etc/runit/reboot chmod 100 /etc/runit/reboot # Set runlevel to: # - single if kernel has param: S # - RUNLEVELNAME if kernel has param: runlevel=RUNLEVELNAME # - default if kernel has no params or unable to set requested runlevel grep -q '\(^\| \)S\( \|$\)' /proc/cmdline && runlevel='single' runsvchdir ${runlevel:-default} || runsvchdir default } SEND_MAIL() { echo -e "To: root\nSubject: reboot at $(date)" | sendmail -t } DMESG() { # Create an 'after-boot' dmesg log dmesg > /var/log/dmesg chmod 640 /var/log/dmesg } PATH=/sbin:/usr/sbin:/bin:/usr/bin trap ':' INT QUIT TSTP . /etc/runit/lib.sh try CONSOLE try INIT startlog /run/boot.log try UDEV try HWCLOCK #try MODULES # Enable & configure this if you have modules support in kernel FSCK try REMOUNT try LOCALMOUNT try SYSCTL try MIGRATERUN try UTMPWTMP try CLEANTMP try RANDOMSEED #try SENSORS # Enable this if you have configured lm_sensors #try LOADKEYS # Enable & configure this for non-english keyboard layout #try SOUND # Enable this if you have sound card (also in /etc/runit/3!) try HOST_NAME # Do not forget to configure this try NETWORK # Do not forget to configure this try RUNIT #try SEND_MAIL # Enable this if you wanna receive notification email on reboot try DMESG stoplog mv /run/boot.log /var/log/boot # Select next stage (exit 0 for stage 2, exit 100 for stage 3): exit 0 


शटडाउन: / etc / runit / 3


 #!/bin/bash CONSOLE() { chvt 1 # Required in case getty was last process in this console and it leave # console in broken state (\n work as <LF> without <CR>). { stty sane ; echo ; } >/dev/console } TERM() { # Give a chance for all processes for clean exit. # This also will kill all 'runsvdir' and signal all 'runsv' to exit. killall5 -15 || [ $? -eq 2 ] } HWCLOCK() { test -f /run/init.hwclock && hwclock --systohc --localtime --noadjfile } SERVICES() { sv force-stop /var/service/* &>/dev/null || : } SOUND() { test -f /run/init.alsa && alsactl -f /etc/asound.state store } RANDOMSEED() { local psz=$(( $(sysctl -n kernel.random.poolsize 2>/dev/null || echo 4096) / 4096 )) (umask 077; dd if=/dev/urandom of=/var/lib/misc/random-seed count=$psz 2>/dev/null) } NETWORK() { ip link set group default down } WTMP() { halt -w } KILL() { # Goodbye to everybody... killall5 -9 || [ $? -eq 2 ] } UMOUNT() { sync; sync # Unmounting loopback devices first: for d in $(grep '^/dev/loop' /proc/mounts | cut -d ' ' -f 2 | tac); do eval "umount -d -r -f $'$d'" done # Unmounting all real filesystems except root: for d in $(egrep -v '^\S+ (/|/dev|/dev/.*|/proc|/proc/.*|/run|/sys|/sys/.*) ' /proc/mounts | cut -d ' ' -f 2 | tac); do eval "umount -r -f $'$d'" done # Switching off swap umount -a -t tmpfs 2>/dev/null || : swapoff -a } PATH=/sbin:/usr/sbin:/bin:/usr/bin trap ':' INT QUIT TSTP . /etc/runit/lib.sh try CONSOLE startlog /var/log/shutdown try TERM try HWCLOCK try SERVICES #try SOUND # Enable this if you have sound card try RANDOMSEED try NETWORK try WTMP try KILL try UMOUNT stoplog 

Source: https://habr.com/ru/post/In21205/


All Articles