/boot/cmdline.txtを使用して、初回起動スクリプトを作成します


11

ネットワーク上でPiを見つける方法について、多くの質問が寄せられています。その他-私自身を含む-は、新しいPiのバッチをデプロイしようとする際に時間がかかる問題があります。

カスタム画像の作成はこれらの問題の解決策になる可能性がありますが、他の解決策があるかどうか疑問に思っています。

通常のマシン(Win / OSX)で/bootアクセスするために(のみ)ディレクトリーが開いている場合、テキストをbashスクリプトにパイプして実行し、後で削除することはできますか?/boot/cmdline.txt


1
この質問はMeta議論中です。できればあなたの意見を聞きたいのですが。ありがとう。
トーマスウェラー

回答:


6

私が作成した、軽くアドレスこの必要性というRaspberian光の修正版を-それは最初の起動時にカスタム/boot/firstboot.shスクリプトを実行します。

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


ありがとう!OPの4年後、ようやく良い解決策があります。自分で構築するのに特にロケット科学ではありませんが、新しいリリースがあるたびに何時間もかかります。これはメインファームウェアに追加する必要があります。
EDP

3

FAT32 ブートパーティションに配置されたスクリプトのみを含むソリューションを好むユーザーのために、以下にその方法を示します。[ 編集:ファイルはプロジェクトpi-boot-scriptで利用できるようになりました。]

他の回答で述べたように、Linuxカーネルの起動に使用されるコマンドライン引数が含まれます。これらの引数は/boot/cmdline.txtにあります。

Raspbian Buster(v10.1)2019-09-26でこれをテストしました。新しくフラッシュされたSDカードまたはダウンロードされた.imgディスクイメージで動作し、任意の数のSDカードにフラッシュできます。

1.カーネル引数を編集します

テキストファイル/boot/cmdline.txtを開き、init=そこからすべての部分を削除して、これを行末に追加します。

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

この行の最後の単語は、/ sbin / initの代わりに、カーネルによって最初のプロセス(PID = 1)として実行されるスクリプトの名前です。カーネル引数のヘルプページには、唯一の引数なしで言う.スクリプトを呼び出すことはできませんので、初期化実行可能ファイルに渡されますunattended.shそのようなものか。

2.スクリプトをブートパーティションに配置します

次を/ unattended(コマンドラインで入力した名前)としてブートパーティションに保存します。

# 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.スクリプトが必要とする他のファイルをブートパーティションに置きます

...明らかに。

私のスクリプトと一緒に、私はLinuxパーティションに移動したいファイルを保持するフォルダーペイロード/をブートパーティションに置きました。上記の無人スクリプトでは、

  • 行Aはファイルをpi-userのディレクトリに移動します。例えば、payload / home / pi / .bashrc/home/pi/.bashrcとしてルートファイルシステムに移動されます。
  • 含むLinuxパーティションにラインBの移動ルートが所有するファイル、ペイロードは/ usr / local /ビン/ 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ユーザーが(アプリケーションログなどに)書き込むことができるようにします。ext4パーティションとファイルシステムをSDカードの残りの部分にサイズ変更します。ロケール、タイムゾーン、ホスト名(CPUシリアル番号に基づく)、WiFi国を変更します。WiFiネットワークとパスフレーズを設定します。SSHをオンにします。SSHセッションの言語設定の問題を修正しました。自動ログインなしでコンソールへの起動を設定します。システムに関するデータをブートパーティション上のファイルに書き込みます。そしてもちろん、そのシンボリックリンクを削除して、起動時に再度実行されないようにします。

ほとんどのユーザーはこれが不要であると感じPiBakerypi-init2、またはカスタムext4イメージを使用することを好みます。これらは優れたソリューションです。私はそれを完全に理解でき、他のソフトウェアを実行する必要がないので、私はこれを好みます。そして、それも機能します。スクリプトを入れた.imgファイルを使用すると、SDカードをフラッシュする+ Piに入れる+実行するために実行するのに6分かかります。

ソース私は、Linuxパーティションのサイズを変更するためにデフォルトで実行されるinit_resize.shスクリプトに、init=カーネル引数としてのスクリプトのアイデアと、mountそれを機能させるために必要なコマンドを見つけました。


2

カーネルのコマンドラインをいじることによってコードを実行させることができます。最も明白な方法は、initを別のものに置き換えることです。これの最も一般的なアプリケーションは、ブートプロセスの非常に早い段階でシェルを起動することです。通常、何かを修正する必要があるか、他のすべてが非常にひどく壊れているためです。

init=/bin/bash

ブートプロセスのこの時点では、ファイルシステムはすべて読み取り専用でマウントされていることに注意してください。さらに、正しく機能しないものもたくさんあります。実際のinitが実行されていないため、シャットダウンと再起動は機能しません。reboot -fたとえば、ルートファイルシステムを読み取り専用で手動で再マウントし、再起動を呼び出す必要があります。

この方法でbashに引数を渡すことができるかどうかはわかりません。私は試したことがない。理論的には、-cbashに渡せれば、そのbashプロセスに何かを実行させることができます。しかし、それはかなり長い議論になる可能性があり、カーネルがそのようなことを許可するかどうかはわかりません。

あなたができる2番目のこと。初期ramfs(initramfs)をファイルシステムにコピーし、それをで使用するようにブートローダーを設定できますconfig.txt。スクリプトをinitramfsに入れて特別なことをする方法はいくつかあります。ただし、この目的のために特別なinitramfsを準備する必要があるため(initramfs-tools(8)を参照)、これがカスタムイメージよりも優れたソリューションであるかどうかはわかりません。

/ bootにスクリプトを含め(「通常の」マシンについての提案を笑いましたが、これはそれらのマシンからアクセスできるビットになります)、カーネルのinit行を使用してそれを起動しようとしますが、dosファイルシステム上のファイルはありませんファイルシステム全体に対してそうしない限り、実行できません。

私の場合、dhcpを使用してネットワークを構成し、起動時に実行されるカスタムスクリプトを含むカスタムイメージを作成します。このスクリプトは、フラグとして機能する特定のファイルをチェックします。ファイルが存在する場合は、何もしません。そうでない場合は、設定を行い、フラグファイルを作成します。

あなたの設定スクリプトは、httpサーバーから本物を引き出すことさえできます。つまり、何かを微調整する必要がある場合、新しい画像を作成する必要はありません。

それが最もストレスの少ないソリューションになるはずです。

最後の可能性の1つですが、「通常ではない」マシンでこれを行う必要があります。標準のRaspbian Jessie画像の場合、次のようになります。

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を実行するのが好きです。最初の起動時にマウント数をゼロに設定します:-)

編集:数ヶ月とより多くの経験の後。あなたはu-bootを見たいです。ブートローダーをu-bootに置き換えます。これは「通常のマシン」から実行できます。u-bootを配置したら、sdカードを簡単にフラッシュできるディストリビューションをネットワークブートするか、理論的にはカードを直接フラッシュできますが、どれほど難しいかはわかりません。

基本的にu-bootはRaspberry Piにネットワークブートをもたらしますが、それ自体ではサポートされません。


その段階では、ファイルシステムは読み取り専用です。どうinit=script & initですか?initが正常に起動している間、スクリプトはバックグラウンドで実行されます。スクリプトは、最初にいくつかの条件チェックを必要とし、たとえば、initがその作業を終了したときに続行します。
Thomas Weller

1
&を使用して何かをバックグラウンドで処理することは、シェルのことです。シェルで特定のコマンドを実行するようにカーネルに指示する場合(例:bash -c "一部のコマンドと別のコマンド")は機能しません。しかし、私は私の答えを拡張し、u-bootオプションを追加しました。これは最近発見したものです。
izak

1
試してみたところ;-)いいえ、実際には機能しません
Thomas Weller

1

ブート領域config.txtで何が行われているかを詳しく理解していない限り、ブート領域(以外)に触れることはお勧めしません。cmdline.txtは、RPiの起動時に実行するようには設計されていません。ブート時にLinuxカーネルにパラメーターを渡すために使用されます。

これはすべてSSHで行うことをお勧めします。デスクトップ上のスクリプトは、bash / python / java / c / whateverプログラムをRPiにプッシュして実行し、終了したら削除することができます。デスクトップ上のスクリプトにスレッドを追加すると、スクリプトを必要な数のデバイスに同時に送信できます。


1
それが現在のやり方ですが、もっと簡単な解決策を探しています。
EDP​​、2016年

1
読む:サーバーが開始するのではなく、クライアントが開始するセットアップを実行する
EDP

@EDP:ブート位置を編集するだけで必要なものを取得する方法はありません。RPiの最初の起動時にサーバーからファイルをプルするスクリプトを記述し、そのプログラムに起動スクリプトを削除させることができます。その場合は、カスタムイメージを使用する必要があります。
Jacobm001

1
「デスクトップ上のスクリプト」-私のデスクトップ上のどのスクリプトですか?初回の起動時には、デスクトップにスクリプトはありません。「これをすべてSSHで行う」-最初の起動時に、PiはイーサネットまたはWLANの設定が正しくない可能性があります。
Thomas Weller

ファブリックプロジェクトをチェックアウトする必要もありません。IIRCの唯一の変更はSSHです
Steve Robillard

1

間違いなく、最初の起動時にスクリプトを自動実行するようにイメージを変更することに問題がなければ、スクリプトと同じ方法でイメージを変更し、そのSDカードをイメージファイルに保存して、フラッシュに使用することができます。新しいRPisで使用するSDカード。たとえば、すべてのRPにの特定のエントリを持たせたい場合は、変更を行うスクリプトを作成する代わりに、自分自身を/etc/fstab変更するだけで済みます/etc/fstab

(各画像は異なる方法で修正する必要がある場合など)あなたは絶対にスクリプトのアクションを必要とする場合、あなたは移動することができます/etc/rc.localにを/etc/rc.bakし、中にスクリプト入れ/etc/rc.localて自分自身に置き換えられた/etc/rc.bak最後のコマンドでは。このスクリプトは、最初のブートアクション自体を実行することも、必要に応じて/bootパーティションから特定のスクリプトを呼び出すこともできます。

ここで/boot説明するように、カーネルに特別なブートRAMディスクイメージを提供することで、パーティションのみを操作して自動実行を行うことができます。そのイメージには、ルートパーティションを変更してからから自己削除するスクリプトが含まれconfig.txtます。でも、それだけの価値があるかどうかはわかりません。


-2

あなたはあなたの問題の解決策を持っている私のプロジェクトNardを見たいかもしれません:

1)ここで説明するように、各SDカードには通常のWindows PCで一意のIDを割り当てることができます:http :
//www.arbetsmyra.dyndns.org/nard/#devsettingsid

2)すべてのPiの電源を入れます

3)可能であればPCファイアウォールを無効にする

4)DOSプロンプトウィンドウを開き、サブネットブロードキャストアドレスにpingを実行します

5)Windowsコマンド "arp -a"でARPテーブルをリストします。リストには、近くにあるすべてのRaspberry PiのMACアドレスとIPアドレスがあります。

6)Telnetで各デバイスに接続します(通常はWindowsでも利用可能です)。ウェルカムフレーズには、手順1で割り当てられたIDが表示されます。


おそらく、私の最初の説明は十分に明確ではありませんでした。私は特にPiを識別する方法を探しているわけではありません。私はすでにそれをカバーしています。私が探しているのは、/ boot / cmdline.txtファイルを変更して、1つ以上のbashコマンドを実行することです。これはすべて、sshを介してログインする必要がなく、一度でも可能です。
EDP

おそらく、「サブネットブロードキャストアドレスにpingを実行する」ことはできません。通常、スマーフ攻撃は防止されます。
CrackerJack9 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.