क्या init प्रक्रिया लिनक्स में एक शेल स्क्रिप्ट हो सकती है?


14

मैं एक कस्टम initramfs की स्थापना पर एक ट्यूटोरियल से गुजर रहा था जहाँ यह बताता है:

केवल एक चीज जो गायब है / init, रूट initramfs की निष्पादन योग्य है जिसे कर्नेल द्वारा लोड किए जाने के बाद निष्पादित किया जाता है। क्योंकि sys-apps / busybox में पूरी तरह कार्यात्मक शेल शामिल है, इसका मतलब है कि आप अपने / init बाइनरी को एक साधारण शेल स्क्रिप्ट के रूप में लिख सकते हैं (इसके बजाय यह असेंबलर या सी में लिखा गया एक जटिल एप्लिकेशन जिसे आप को संकलित करना है)।

और एक शेल स्क्रिप्ट के रूप में init का एक उदाहरण देता है जो इसके साथ शुरू होता है #!/bin/busybox sh

अब तक, मैं इस धारणा के तहत था कि यह मुख्य प्रक्रिया है जो लॉन्च की गई है और यह कि अन्य सभी उपयोगकर्ता अंतरिक्ष प्रक्रिया अंततः इनिट के बच्चे हैं। हालांकि, दिए गए उदाहरण में, पहली प्रक्रिया वास्तव में है bin/busybox/ sh, जिसमें से बाद में इनवॉइस पैदा की जाती है।

क्या यह सही इंटरपर्टेशन है? यदि मैं, उदाहरण के लिए, उस बिंदु पर उपलब्ध दुभाषिया उपलब्ध है, तो मैं एक अजगर स्क्रिप्ट आदि के रूप में इनिट लिख सकता हूं?

जवाबों:


12

init "spawned" (एक बच्चे की प्रक्रिया के रूप में) नहीं है, बल्कि execइस तरह से है:

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

execपूरी प्रक्रिया को जगह देता है। अंतिम इनिट अभी भी पहली प्रक्रिया है (पीआईडी ​​1), भले ही यह इनट्राम्रफ़्स में उन लोगों से पहले था।

Initramfs /init, जो pid ​​1 के साथ एक बिजीबॉक्स शेल स्क्रिप्ट है, बिज़ीबॉक्स के execलिए है switch_root(इसलिए अब switch_rootpid 1 है); यह प्रोग्राम आपके आरोह बिंदुओं को बदलता है इसलिए /mnt/rootनया होगा /

switch_rootफिर अपने असली रूट फाइलसिस्टम के execलिए फिर से /sbin/init; इसके अलावा यह आपके वास्तविक init सिस्टम को pid ​​1 के साथ पहली प्रक्रिया बनाता है, जो बदले में किसी भी बच्चे की प्रक्रिया को स्पॉन कर सकता है।

निश्चित रूप से यह सिर्फ पायथन लिपि के साथ किया जा सकता है, अगर आप किसी तरह से पायथन को अपने इनिट्रामेफ़्स में सेंध लगाने में कामयाब रहे। हालाँकि, यदि आप किसी भी तरह से बिजीबॉक्स को शामिल करने की योजना नहीं बनाते हैं, तो आपको इसकी कुछ कार्यक्षमता (जैसे switch_root, और आमतौर पर आप एक साधारण कमांड के साथ करेंगे) को फिर से लागू करना होगा।

हालांकि, यह गुठली पर काम नहीं करता है जो स्क्रिप्ट बायनेरिज़ ( CONFIG_BINFMT_SCRIPT=y) की अनुमति नहीं देता है , या ऐसे मामले में आपको सीधे दुभाषिया शुरू करना होगा और इसे अपनी स्क्रिप्ट को किसी भी तरह लोड करना होगा।


/पतली हवा में गायब नहीं होता है - यह ऊपर चढ़ाया जाता है (हालांकि आमतौर पर इसकी सामग्री सभी को नष्ट कर दी जाती है इससे पहले कि यह मेमोरी को बचाने के लिए है) । यह अब भी हैswitch_rootsyscall करता है switchroot- जो कर्नेल देवता प्रदान करता है जब उन्होंने बूट प्रक्रिया को कर्नेल 2.6 में बदल दिया था। यह कर्नेल है जो जादू करता है।
mikeserv

1
एक switchrootsyscall वास्तव में मेरे लिए खबर होगी। क्या तुम्हारे पास उसका कोई स्रोत है? यदि आप switch_root.c स्रोत कोड को देखते हैं, तो यह काफी मैन्युअल प्रक्रिया प्रतीत होती है, और जैसा कि दस्तावेज़ीकरण / filesystems / ramfs-rootfs-initramfs.txt में वर्णित है। इसके अलावा, अगर आप सब कुछ हटा दें और इसे माउंट कर दें, तो यह इस बिंदु पर बहुत गायब हो गया है, आपको नहीं लगता?
फ्रॉस्ट्सचुट्ज़

pivot_rootदूसरी ओर, एक syscall है। यह switch_rootहालांकि इसके लिए उपयोग नहीं किया जाता है और कुछ हुप्स के माध्यम से कूद के बिना उपयोग नहीं किया जा सकता है, और किसी भी तरह से यह इस जवाब के लिए कोई मायने नहीं रखता है, इसलिए मैंने इसे पूरी तरह से हटा दिया। बहुत बुरा, मैंने सोचा कि जादू और पतली हवा में गायब हो गया वास्तव में अच्छी तरह से काम किया ... :-P
frostschutz

खैर, हो सकता है कि मुझे इसके बारे में गलत विचार आया switch_root- जिसके लिए मुझे खेद है, और मुझे दिखाने के लिए मैं आपको धन्यवाद देता हूं - लेकिन यह वैसे भी गायब नहीं होता है। initramfs जड़ बनी रहती है और हर किसी के लिए हमेशा वहाँ है - यह है जड़।
मिकसेर्व

1
जैसा कि आपने डॉक्स से कहा है : लेकिन initramfs रूटफ़्स है: आप रूटफ़ुट को न तो पिवट कर सकते हैं, न ही इसे अनमाउंट कर सकते हैं। स्थान को खाली करने के लिए find -xdev / -exec rm '{}' ';'रूटफ़्स से सब कुछ हटाने के बजाय ( ), नई रूट ( cd /newmount; mount --move . /; chroot .) के साथ रूटफ़ॉम्स को ओवरमाउंट करें, स्टड / स्टडआउट / स्टेडर को नए / देव / कंसोल में संलग्न करें, और नए इनिट को निष्पादित करें ।
मोकेसर

4

लिनक्स कर्नेल का निष्पादन syscall देशी रूप से शेबंग को कम करता है

जब निष्पादित फ़ाइल मैजिक बाइट्स से शुरू होती है #!, तो वे कर्नेल का उपयोग करने के लिए कहते हैं #!/bin/sh:

  • करो और execसिस्टम कॉल करो
  • निष्पादन योग्य के साथ /bin/sh
  • और CLI तर्क के साथ: वर्तमान स्क्रिप्ट के लिए पथ

यह ठीक वैसा ही है जैसा कि तब होता है जब आप एक नियमित यूजरलैंड शेल स्क्रिप्ट चलाते हैं:

./myscript.sh

यदि फ़ाइल के .ELFबजाय मैजिक बाइट्स के साथ शुरू हुआ था #!, तो कर्नेल इसे चलाने के बजाय ELF लोडर को ले जाएगा।

अधिक विवरण: लोग पायथन लिपि की पहली पंक्ति पर #! / Usr / bin / en python shebang क्यों लिखते हैं? | स्टैक ओवरफ़्लो

एक बार जब आपके पास यह हो जाता है, तो यह स्वीकार करना आसान हो जाता है कि /initकुछ भी हो सकता है जो कर्नेल एक शेल स्क्रिप्ट सहित निष्पादित कर सकता है, और यह भी कि /bin/shउस मामले में पहला निष्पादन योग्य क्यों होगा।

यहां उन लोगों के लिए एक न्यूनतम रननीय उदाहरण दिया गया है जो इसे आज़माना चाहते हैं: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/cbea7cc02c86871110918e1a261d01fd0473eea0b#custom-inititit

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.