पहली बूट स्क्रिप्ट बनाने के लिए /boot/cmdline.txt का उपयोग करें


11

मेरे नेटवर्क पर मेरे पाई को खोजने के तरीके के बारे में कई सवाल पूछे गए हैं । दूसरों - अपने आप सहित - समय लेने वाली समस्याएँ हैं जबकि ताजा पाई के एक बैच को तैनात करने की कोशिश कर रहे हैं।

हालांकि कस्टम छवियों का निर्माण इन मुद्दों का समाधान हो सकता है, मैं सोच रहा हूं कि क्या अन्य समाधान हैं।

नियमित मशीनों (विन / ओएसएक्स) /bootपर पहुंच के लिए (केवल) निर्देशिका के साथ खुला , क्या यह संभव है कि पाठ को एक बश लिपि में पाइप करने के लिए उपयोग किया जाए, इसे चलाएं और बाद में इसे हटा दें?/boot/cmdline.txt


1
इस सवाल पर मेटा पर चर्चा चल रही है । यदि संभव हो तो मैं आपकी राय सुनना चाहूंगा। धन्यवाद।
थॉमस वेलर

जवाबों:


6

मैंने रास्पबेरियन-लाइट का एक हल्का संशोधित संस्करण बनाया जो इस आवश्यकता को संबोधित करता है - यह आपके कस्टम /boot/firstboot.sh स्क्रिप्ट को पहले बूट पर निष्पादित करता है:

https://github.com/nmcclain/raspberian-firstboot


धन्यवाद! ओपी के 4 साल बाद आखिरकार एक अच्छा समाधान है। इसे बनाने के लिए विशेष रूप से रॉकेट साइंस नहीं, बल्कि हर बार जब आप एक नया रिलीज़ करते हैं तो कई घंटों के लिए। IMHO इसे मुख्य फर्मवेयर में जोड़ा जाना चाहिए।
EDP

3

जो लोग केवल स्क्रिप्ट से जुड़े समाधान को पसंद करते हैं, उनके लिए FAT32 बूट पार्टीशन में छोड़ दिया गया है , यहाँ बताया गया है कि यह कैसे करना है। [ संपादित करें: फाइलें अब प्रोजेक्ट पी-बूट-स्क्रिप्ट में उपलब्ध हैं ।]

जैसा कि अन्य उत्तरों में उल्लेख किया गया है, इसमें कमांड-लाइन तर्क शामिल हैं जिसके साथ लिनक्स कर्नेल शुरू किया गया है। वे तर्क /boot/cmdline.txt में हैं

मैंने रास्पियन बस्टर (v10.1) 2019-09-26 पर इसका परीक्षण किया है। यह एक नए फ्लैश किए गए एसडी कार्ड पर या डाउनलोड की गई .img डिस्क छवि पर काम करता है , जिसे आप किसी भी एसडी कार्ड में फ्लैश कर सकते हैं।

1. कर्नेल तर्कों को संपादित करें

पाठ फ़ाइल खोलें /boot/cmdline.txt , इसमें से किसी भी init=भाग को हटा दें , और इसे पंक्ति के अंत में जोड़ें:

init=/bin/bash -c "mount -t proc proc /proc; mount -t sysfs sys /sys; mount /boot; source /boot/unattended"

इस लाइन पर अंतिम शब्द कर्नेल द्वारा पहली प्रक्रिया (PID = 1) के बजाय / sbin / init के रूप में चलाने के लिए एक स्क्रिप्ट का नाम है । कर्नेल-तर्क मदद पृष्ठ केवल तर्क के बिना कहते हैं .init एक्ज़िक्यूटेबल में पास हो, तो आप स्क्रिप्ट कॉल नहीं कर सकते unattended.sh या ऐसा बातें।

2. स्क्रिप्ट को बूट पार्टीशन पर रखें

बूट पार्टीशन को निम्नलिखित के रूप में सहेजें / अनअटेंडेड (कमांड लाइन में आपके द्वारा डाला गया नाम):

# 1. MAKING THE SYSTEM WORK. DO NOT REMOVE
mount -t tmpfs tmp /run
mkdir -p /run/systemd
mount / -o remount,rw
sed -i 's| init=.*||' /boot/cmdline.txt

# 2. THE USEFUL PART OF THE SCRIPT
# Example:
[[ -d /boot/payload/home/pi ]] && sudo -u pi cp --preserve=timestamps -r\
 /boot/payload/home/pi /home/ && rm -rf /boot/payload/home/pi              # A
[[ -d /boot/payload ]] && cp --preserve=timestamps -r /boot/payload/* /\
 && rm -rf /boot/payload                                                   # B
ln -s /lib/systemd/system/one-time-script.service\
 /etc/systemd/system/multi-user.target.wants/                              # C

# 3. CLEANING UP AND REBOOTING
sync
umount /boot
mount / -o remount,ro
sync
echo 1 > /proc/sys/kernel/sysrq
echo b > /proc/sysrq-trigger
sleep 5

यह स्क्रिप्ट कुछ आवश्यक तैयारी (अध्याय 1) करता है, फिर कुछ भी आप करना चाहते हैं (2) और फिर सफाई और फिर से बूटिंग (3)। आप जो आदेश चलाना चाहते हैं, उसके तहत सामान को 2 से बदलें।

कुछ कॉन्फ़िगरेशन कार्यों के लिए आपको संभवतः नेटवर्किंग और अन्य सेवाओं को लाने के लिए एक सामान्य बूट की आवश्यकता होती है, इसलिए इस संस्करण में उदाहरण (नीचे समझाया गया है) केवल Pi स्क्रिप्ट को चलाने के लिए एक उचित स्क्रिप्ट के लिए तैयार करता है।

3. बूट विभाजन पर आपकी स्क्रिप्ट की ज़रूरतों के लिए कोई अन्य फ़ाइल रखें

...जाहिर है।

उदाहरण

अपनी स्क्रिप्ट के साथ, मैंने एक बूट पेलोड / बूट विभाजन पर रखा, जो उन फ़ाइलों को रखता है जिन्हें मैं लिनक्स विभाजन में स्थानांतरित करना चाहता हूं। स्क्रिप्ट में पहुंच से बाहर से ऊपर,

  • लाइन A फाइल को pi-user की डायरेक्टरी में ले जाती है। उदाहरण के लिए पेलोड / होम / पीआई / .bashrc को रूट फाइल सिस्टम में /home/pi/.bashrc पर ले जाया जाता है ;
  • लाइन बी चाल सहित लिनक्स विभाजन, में जड़ के स्वामित्व वाली फ़ाइलों पेलोड / usr / स्थानीय / bin / one-time-script.sh जो हो जाता है /usr/local/bin/one-time-script.sh , और के लिए इसी तरह के पेलोड / lib / systemd / system / one-time-script.service ;
  • लाइन C तब उस अंतिम फ़ाइल के लिए एक सिम्लिंक बनाता है, इसलिए मेरी कॉन्फ़िगरेशन स्क्रिप्ट one-time-script.sh अगले बूट पर चलाई जाती है।

वह स्क्रिप्ट मुझे पसंद है विभिन्न अनुकूलन करता है: यह एक और FAT32 विभाजन बनाता है और प्रारूपित करता है और इसे / etc / fstab में जोड़ता है ताकि pi उपयोगकर्ता इसे (एप्लिकेशन लॉग आदि के लिए) लिख सके; शेष 4 विभाजन और फाइल सिस्टम को एसडी कार्ड के शेष भाग में बदल देता है; स्थान, समयक्षेत्र, होस्टनाम (सीपीयू सीरियल नंबर के आधार पर), वाईफाई देश; वाईफाई नेटवर्क और पासफ़्रेज़ सेट करता है; SSH को चालू करता है; SSH सत्रों के लिए भाषा-सेटिंग समस्या को हल करता है; ऑटो-लॉगिन के बिना कंसोल में बूटिंग को कॉन्फ़िगर करता है; बूट विभाजन पर एक फाइल के लिए सिस्टम के बारे में कुछ डेटा लिखते हैं; और निश्चित रूप से यह उस सिम्कलिन को हटा देता है ताकि वह बूट पर फिर से न चले।

अधिकांश उपयोगकर्ता इसे अनावश्यक पाएंगे और PiBakery , pi-init2 , या एक कस्टम ext4 छवि का उपयोग करना पसंद करेंगे , जो महान समाधान है। मैं इसे पसंद करता हूं क्योंकि मैं इसे पूरी तरह से समझ सकता हूं और मुझे अन्य सॉफ्टवेयर चलाने की जरूरत नहीं है। और यह भी काम करता है: .img फ़ाइल के साथ मैंने अपनी स्क्रिप्ट्स को अंदर डाला है, सभी एक एसडी कार्ड को चमकाने + इसे एक पाई + में डालने से इसे कॉन्फ़िगर करने के लिए 6 मिनट लगते हैं।

स्रोत मुझे एक स्क्रिप्ट का विचार init=कर्नेल तर्क के रूप में मिला , और mountयह काम करने के लिए आवश्यक कमांड्स, init_resize.sh स्क्रिप्ट जो डिफ़ॉल्ट रूप से लिनक्स विभाजन का आकार बदलने के लिए चलती है।


2

आप कर्नेल कमांड लाइन के साथ गड़बड़ करके कोड को निष्पादित कर सकते हैं। सबसे स्पष्ट तरीका कुछ और के साथ init को बदलना है। इसका सबसे आम अनुप्रयोग बूट प्रक्रिया में बहुत पहले एक शेल लॉन्च करना है, आमतौर पर क्योंकि आपको कुछ ठीक करने की आवश्यकता होती है या क्योंकि बाकी सब कुछ बहुत बुरी तरह से टूट जाता है, जैसे:

init=/bin/bash

ध्यान रखें कि बूट प्रक्रिया में इस बिंदु पर, फ़ाइल सिस्टम सभी अभी भी केवल पढ़ने के लिए आरोहित हैं। इसके अलावा, वहाँ चीजों का एक पूरा गुच्छा है जो सिर्फ सही ढंग से काम नहीं करेगा। क्योंकि आपके पास वास्तविक इनिट नहीं है, इसलिए शटडाउन और रीबूट काम नहीं करेगा। आपको मैन्युअल रूप से केवल पढ़ने के लिए रूट फाइल सिस्टम को रिमूव करना होगा और reboot -fउदाहरण के लिए रिबूट पर कॉल करना होगा।

मुझे कोई अंदाजा नहीं है कि क्या आप इस तरीके से बहस करने के लिए तर्क दे सकते हैं। मैंने कभी कोशिश नहीं की है। सिद्धांत रूप में, यदि आप -cबैश करने के लिए पास कर सकते हैं, तो आप कुछ भी करने के लिए उस बैश प्रक्रिया को बता सकते हैं। लेकिन यह काफी लंबे तर्क में बदल सकता है, और मुझे नहीं पता कि कर्नेल ऐसी चीजों की अनुमति देगा या नहीं।

दूसरी बात आप कर सकते हैं। आप फ़ाइल सिस्टम के लिए एक प्रारंभिक रम्फ (initramfs) की प्रतिलिपि बना सकते हैं, और इसे उपयोग करने के लिए बूटलोडर को कॉन्फ़िगर कर सकते हैं config.txt। विशेष कार्य करने के लिए स्क्रिप्ट को इनट्राम्राम्स में लाने के कई तरीके हैं। आपको इस उद्देश्य के लिए एक विशेष initramfs तैयार करना होगा (initramfs-tools (8) देखें), इसलिए मुझे यकीन नहीं है कि यह एक कस्टम छवि की तुलना में बेहतर समाधान है।

आप स्क्रिप्ट को / बूट में शामिल कर सकते हैं (मैंने "नियमित" मशीनों के बारे में आपके सुझाव पर हँसते हुए कहा, लेकिन यह वही होगा जो आप उन मशीनों से एक्सेस कर सकते हैं) और कर्नेल इनिट लाइन का उपयोग करके लॉन्च करने का प्रयास करेंगे, लेकिन डॉस फाइल सिस्टम पर फाइलें आ सकती हैं जब तक आप इसे पूरे फाइलसिस्टम के लिए नहीं बनाते तब तक यह निष्पादन योग्य नहीं होगा।

यदि यह मैं था, तो मैं एक कस्टम छवि बनाऊंगा जो नेटवर्क को कॉन्फ़िगर करने के लिए dhcp का उपयोग करता है, और इसमें एक कस्टम स्क्रिप्ट होती है जो बूट पर चलती है। यह स्क्रिप्ट एक विशिष्ट फ़ाइल की जांच करती है जो एक ध्वज के रूप में कार्य करती है। यदि फ़ाइल मौजूद है, तो कुछ भी न करें। यदि नहीं, तो चीजों को कॉन्फ़िगर करें, फिर ध्वज फ़ाइल बनाएं।

आपकी कॉन्फ़िग स्क्रिप्ट http सर्वर से वास्तविक चीज़ भी खींच सकती है। इसका मतलब है कि अगर आपको कुछ नया करना है तो आपको एक नई छवि बनाने की ज़रूरत नहीं है।

यह कम से कम तनावपूर्ण समाधान होना चाहिए।

एक अंतिम संभावना, लेकिन आपको यह "गैर-नियमित" मशीन पर करना होगा :-) आप ext4 फाइल सिस्टम को लूप डिवाइस पर माउंट कर सकते हैं और इसे पहले sdcard पर लिखे बिना फाइल कॉपी कर सकते हैं। एक मानक रास्पियन जेसी छवि के लिए, यह कुछ इस तरह होगा:

sudo losetup /dev/loop0 /tmp/gw.img -o 62914560
sudo mount /dev/loop0 /mnt
sudo cp /my/superduper/script.sh /mnt
sudo umount /dev/loop0
sudo fsck -f /dev/loop0 # This is optional
sudo losetup -d /dev/loop0

मैं छवियों को बनाने से पहले अपने फाइल सिस्टम पर एक मजबूर fsck करना पसंद करता हूं। पहले बूट पर शून्य तक माउंट गिनती सेट करें :-)

EDIT : कई महीनों और अधिक अनुभव के बाद। आप यू-बूट देखना चाहते हैं। बूट-लोडर को यू-बूट से बदलें। यह एक "नियमित मशीन" से किया जा सकता है। एक बार जब आपके पास यू-बूट हो जाता है, तो आप या तो नेटवर्क-बूट वितरण कर सकते हैं जिससे आप आसानी से एसडी-कार्ड फ्लैश कर सकते हैं, या आप सिद्धांत रूप में कार्ड को सीधे फ्लैश कर सकते हैं, हालांकि मुझे नहीं पता कि यह कितना कठिन होगा।

अनिवार्य रूप से यू-बूट रास्पबेरी पाई के लिए नेटवर्क-बूट लाता है, कुछ ऐसा नहीं है जो अपने दम पर समर्थन नहीं करता है।


ठीक है, फ़ाइल सिस्टम उस स्तर पर आसानी से पढ़ा जाता है। किस बारे में init=script & init? स्क्रिप्ट सामान्य रूप से शुरू होने के दौरान पृष्ठभूमि में चलेगी। स्क्रिप्ट को शुरुआत में कुछ कंडीशन की जाँच की आवश्यकता होगी और उदाहरण के लिए जारी रखें जब init ने अपना काम पूरा कर लिया है।
थॉमस वेलर

1
किसी चीज़ को बैकग्राउंड में इस्तेमाल करना एक शेल चीज़ है। जब तक आप कर्नेल को शेल में एक विशिष्ट कमांड चलाने के लिए कहते हैं (जैसे: bash -c "कुछ कमांड और अन्य कमांड") जो काम नहीं करेगा, और मुझे पहले से लगता है कि यह एक बुरा विचार है। लेकिन मैंने अपना जवाब बढ़ाया और यू-बूट विकल्प जोड़ा, जो मैंने हाल ही में खोजा था।
izak

1
बस की कोशिश कर रहा ;-) नहीं समाप्त होने पर, यह वास्तव में नहीं काम करता है
थॉमस वेलर

1

मैं बूट क्षेत्र में कुछ भी छूने की सलाह नहीं दूंगा ( config.txtतब तक) जब तक आपको उस सामान की विस्तृत समझ नहीं होगी। cmdline.txtआरपीआई शुरू होने पर चीजों को चलाने के लिए डिज़ाइन नहीं किया गया है। इसका उपयोग बूट पर लिनक्स कर्नेल के मापदंडों को पारित करने के लिए किया जाता है।

मैं SSH के माध्यम से यह सब करने का सुझाव दूंगा। आपके डेस्कटॉप पर एक स्क्रिप्ट एक bash / python / java / c / जो भी RPi को प्रोग्राम करता है, उस पर अमल कर सकता है, और फिर इसे समाप्त होने पर हटा सकता है। अपने डेस्कटॉप पर स्क्रिप्ट में थ्रेडिंग जोड़ें और आप इसे एक ही समय में जितने चाहें उतने डिवाइस पर भेज सकते हैं।


1
हम इसे अभी कैसे करते हैं, लेकिन मैं एक और आसान समाधान ढूंढ रहा हूं।
EDP

1
पढ़ें: सर्वर शुरू करने के बजाय सेटअप क्लाइंट शुरू करें
EDP

@EDP: बूट पोजीशन को एडिट करके आप जो चाहते हैं उसे पाने का कोई तरीका नहीं है। आप एक स्क्रिप्ट लिख सकते हैं जो आरपीआई के पहले बूट पर सर्वर से फ़ाइल खींचती है, और फिर उस प्रोग्राम को स्टार्टअप स्क्रिप्ट को हटा दें। इसके लिए आपको एक कस्टम छवि का उपयोग करना होगा।
Jacobm001

1
"आपके डेस्कटॉप पर एक स्क्रिप्ट" - मेरे डेस्कटॉप पर कौन सी स्क्रिप्ट है? पहले बूट में, डेस्कटॉप पर कोई स्क्रिप्ट नहीं है। "SSH के माध्यम से यह सब करना" - पहले बूट में पाई में सही ईथरनेट या WLAN सेटिंग्स नहीं हो सकती हैं।
थॉमस वेलर

आपको फैब्रिक प्रोजेक्ट की जांच करने की भी आवश्यकता नहीं है। IIRC इसकी एकमात्र प्रतिपूर्ति SSH है
स्टीव

1

यकीनन, यदि आप पहले बूट में स्क्रिप्ट को ऑटो-रन करने के लिए छवि को संशोधित करने के साथ ठीक हैं, तो आप बस अपनी स्क्रिप्ट के तरीके से छवि को संशोधित कर सकते हैं और फिर उस एसडी कार्ड को एक छवि फ़ाइल में सहेज सकते हैं और इसे फ्लैश करने के लिए उपयोग कर सकते हैं। एसडी कार्ड जो आप नए RPis के साथ उपयोग करने जा रहे हैं। उदाहरण के लिए, यदि आप चाहते हैं कि आपकी सभी आरपीआई में एक निश्चित प्रविष्टि हो /etc/fstab, तो आप केवल /etc/fstabएक स्क्रिप्ट लिखने के बजाय खुद को संशोधित कर सकते हैं जो संशोधन करता है।

यदि आपको पूरी तरह से स्क्रिप्ट की गई क्रियाओं की आवश्यकता है (जैसे यदि प्रत्येक छवि को एक अलग तरीके से संशोधित किया जाना चाहिए), तो आप अपनी स्क्रिप्ट /etc/rc.localको स्थानांतरित कर सकते हैं /etc/rc.bakऔर एक स्क्रिप्ट डाल सकते हैं /etc/rc.localजिसमें /etc/rc.bakअंतिम कमांड में खुद को बदल देता है । वह स्क्रिप्ट पहले बूट क्रियाओं को स्वयं कर सकती है, या /bootयदि आप चाहें तो विभाजन से किसी विशेष स्क्रिप्ट को कॉल कर सकती हैं।

यहां/boot बताए गए अनुसार कर्नेल को एक विशेष बूट रैमडिस्क छवि की आपूर्ति करके, केवल विभाजन को स्पर्श करके ऑटो-रन बनाना संभव है । उस छवि में रूट विभाजन को संशोधित करने और फिर सेल्फ-डिलीट करने के लिए स्क्रिप्ट होगी config.txt। मुझे यकीन नहीं है अगर यह परेशानी के लायक है, हालांकि।


-2

आप मेरी परियोजना नारद को देखना चाहते हैं जिसमें आपकी समस्या का समाधान है:

1) प्रत्येक एसडी-कार्ड को एक नियमित रूप से विंडोज पीसी के साथ एक अद्वितीय आईडी सौंपा जा सकता है जैसा कि यहां वर्णित है:
http://www.arbetsmyra.dyndns.org/nard/#devsettingsid

2) अपने सभी पिस पर पावर

3) यदि संभव हो तो पीसी फ़ायरवॉल को अक्षम करें

4) एक डॉस प्रॉम्प्ट विंडो खोलें और सबनेट प्रसारण पते को पिंग करें

5) विंडोज कमांड "arp -a" के साथ ARP तालिका को सूचीबद्ध करें। सूची में आपको आस-पास के रास्पबेरी पाई के मैक और आईपी पते मिलेंगे।

6) टेलनेट के साथ प्रत्येक डिवाइस से कनेक्ट करें (आमतौर पर विंडोज में भी उपलब्ध है)। स्वागत वाक्यांश चरण 1 में दी गई आईडी को प्रदर्शित करेगा।


शायद मेरा प्रारंभिक विवरण पर्याप्त स्पष्ट नहीं था। मैं विशेष रूप से पाई की पहचान करने के तरीके की तलाश में नहीं हूं। मेरे पास पहले से ही कवर है। जो मैं देख रहा हूँ वह /boot/cmdline.txt फ़ाइल में परिवर्तन करके एक या एक से अधिक bash कमांड चलाने के लिए है। यह सब ssh के माध्यम से प्रवेश करने की आवश्यकता के बिना - एक बार भी।
EDP

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