Answers:
我创建了一个轻度修改的Raspberian-light版本来解决此需求-它在首次启动时执行您的自定义/boot/firstboot.sh脚本:
对于那些只希望将脚本放到FAT32 引导分区中的脚本的解决方案的人,这里是这样做的方法。[ 编辑:这些文件现在可以在项目pi-boot-script中使用。]
如其他答案所述,它涉及启动Linux内核的命令行参数。这些参数在/boot/cmdline.txt中。
我已经在Raspbian Buster(v10.1)2019-09-26上对此进行了测试。它可以在新刷新的SD卡或下载的.img磁盘映像上工作,然后可以将其闪存到任意数量的SD卡上。
打开文本文件/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或类似的东西。
将以下内容另存为/ 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重启时运行正确的脚本。
...明显。
与脚本一起,我在启动分区上放置了一个目录payload /,其中包含要移至Linux分区的文件。在上面无人参与的脚本中,
该脚本可以进行各种我喜欢的自定义:它创建并格式化另一个FAT32分区,并将其添加到/ etc / fstab中,以便pi用户可以对其进行写入(用于应用程序日志等);将ext4分区和文件系统调整为SD卡的其余部分;更改语言环境,时区,主机名(基于CPU序列号),WiFi国家/地区;设置WiFi网络和密码;开启SSH;修复了SSH会话的语言设置问题;配置引导到控制台而无需自动登录;将有关系统的一些数据写入引导分区上的文件;当然,它会删除该符号链接,因此它不会在启动时再次运行。
大多数用户会发现这是不必要的,他们更喜欢使用PiBakery,pi-init2或自定义ext4映像,这是很好的解决方案。我更喜欢这样做,因为我可以完全理解它,而不必运行其他软件。而且它也可以正常工作:使用.img文件,我将脚本放入其中,所有操作都需要刷新SD卡+将其放入Pi中+使其运行以自行配置需要6分钟。
来源我在默认运行的init_resize.sh脚本中找到了将脚本作为init=
内核参数以及mount
使该脚本工作所需的命令的想法,以调整Linux分区的大小。
您可以通过混淆内核命令行来执行代码。最明显的方法是用其他东西代替init。最常见的应用是在引导过程的早期就启动外壳程序,通常是因为您需要修复某些东西,或者因为其他所有东西都严重损坏,例如:
init=/bin/bash
请记住,在引导过程的这一点上,文件系统都仍以只读方式安装。此外,还有很多事情将无法正常工作。因为您没有真正的init运行,所以关机和重新启动将不起作用。例如,您必须手动以只读方式重新挂载根文件系统并调用reboot -f
以重新引导。
我不知道您是否可以通过这种方式将参数传递给bash。我从未尝试过。从理论上讲,如果您可以传递-c
给bash,则可以告诉bash进程可以执行任何操作。但这可能会变成一个相当长的争论,而且我不知道内核是否会允许这样的事情。
您可以做的第二件事。您可以将初始ramfs(initramfs)复制到文件系统,并配置bootloader以在中使用它config.txt
。有几种方法可以将脚本放入initramfs中以执行特殊操作。但是,您必须为此准备一个特殊的initramfs(请参阅initramfs-tools(8)),所以我不确定这是否比自定义图像更好的解决方案。
您可以将脚本包含在/ boot中(我对您对“常规”计算机的建议很满意,但这是您可以从这些计算机访问的位),然后尝试使用内核init行启动该脚本,但是dos文件系统上的文件不是除非您对整个文件系统都如此,否则不能执行。
如果是我,我会制作一个使用dhcp来配置网络的自定义映像,其中包含一个在启动时运行的自定义脚本。该脚本检查充当标志的特定文件。如果文件存在,则不执行任何操作。如果没有,请进行配置,然后创建标志文件。
您的配置脚本甚至可以从http服务器提取真实信息。这意味着,如果必须进行调整,则不必制作新图像。
那应该是压力最小的解决方案。
最后一种可能,但是您必须在“非常规”计算机上执行此操作:-)您可以将ext4文件系统挂载到循环设备上,然后将文件复制到该设备上,而无需先将其写入sdcard。对于标准的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完成工作后继续。
我不建议您触摸引导区中的任何内容(除外config.txt
),除非您对这些东西在做什么有所了解。cmdline.txt
RPi启动时并不是为了运行事物而设计的。它用于在启动时将参数传递给Linux内核。
我建议通过SSH完成所有操作。桌面上的脚本可以将bash / python / java / c /任何程序推送到RPi,执行该程序,然后在完成后将其删除。将线程添加到桌面上的脚本中,然后可以将其同时发送到任意数量的设备。
可以说,如果您可以通过在第一次启动时修改映像以自动运行脚本的方式来确定,则可以按照脚本的方式修改映像,然后将该SD卡保存到映像文件中并使用它进行闪存您要与新RPis一起使用的SD卡。例如,如果您希望所有RPis在中都有某个条目/etc/fstab
,则可以简单地进行/etc/fstab
自我修改,而无需编写脚本进行修改。
如果你绝对需要脚本操作(例如,如果每个图像应该以不同的方式进行修改),你可以将你/etc/rc.local
要/etc/rc.bak
放一个脚本/etc/rc.local
与替换自己/etc/rc.bak
在最后的命令。该脚本本身可以执行第一次引导操作,或者可以根据需要从/boot
分区中调用特定脚本。
这是可能通过触摸仅作自动运行/boot
的分区,通过描述内核提供一个特殊的引导ramdisk映像这里。该映像将包含用于修改根分区,然后从中自删除的脚本config.txt
。我不确定是否值得这样做。
您可能想看一下我的Nard项目,它为您的问题提供了解决方案:
1)可以使用常规Windows PC为每个SD卡分配唯一的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。