更新:
我已经成功创建了一个非常简单的演示使用init=
bootparam 指定应使用自定义二进制文件(用 golang 编写并编译)来代替标准 init。该项目中的二进制文件是针对 Raspberry Pi 的 ARM 处理器编译的,但源代码应该针对任何平台进行编译。
原帖:
我已经成功放入init=/bin/bash
我的启动参数并在启动时获得 root shell。现在我想使用 bootparams 运行“首次启动”设置脚本。
笔记:
我知道可以提供很多替代方案。如果您愿意,请将这些作为对问题的评论。但是,我不能使用它们;这个问题与他们无关;它们不是这个问题的答案。所以,请不要发布替代方案作为答案.* 这对来这里问这个问题的人没有帮助。
我尝试过失败的事情:
init="/bin/bash -c 'mount /dev/mmcblk0p1 /boot; date > /boot/test.txt'"
init='/bin/bash -c "mount /dev/mmcblk0p1 /boot; date > /boot/test.txt"'
init="/bin/bash"
init='/bin/bash'
所以我假设即使引用你的init=
参数也不是一个选择。
- 如果我在这里错了,请纠正我。
我读过了Linux 内核文档就此事。它说:
内核从内核命令行解析参数到
--
;如果它无法识别参数并且不包含 a.
,则该参数将传递给 init:参数=
进入 init 的环境,其他参数将作为命令行参数传递给 init。之后的所有内容--
都作为参数传递给 init。...
init= [KNL] Format: <full_path> Run specified binary instead of /sbin/init as init process.
学过的知识:
这Format: <full_path>
可以解释为什么它不喜欢我在其中放置完整的命令(或多个)init=
我也读过引导参数(7)(搜索“传递给 init 进程”)他们说:
任何不被接受为上述设置函数的“foo=bar”形式的内容都会被解释为要设置的环境变量。一个(无用?)示例是使用“TERM=vt100”作为启动参数。
任何未被内核拾取并且未被解释为环境变量的剩余参数都会被传递到 PID 1,通常是 init(1) 程序。传递给 init 进程的最常见参数是“single”一词,它指示它以单用户模式启动计算机,而不是启动所有常用的守护进程。检查系统上安装的 init(1) 版本的手册页,了解它接受哪些参数。
- 是否有任何使用此信息将参数传递给自定义指定的工作示例
init=
?
如果有的话,很难找到,这个问题将使它出现在谷歌结果中。如果没有,我们将为社区创建一个工作示例。
答案1
是的,这就是传统上告诉常规 init 系统要启动到什么状态的方式。如果您正在运行 sysv-init(或除了 systemd 之外的几乎任何广泛使用的 init 系统),您可以在内核参数末尾放置一个 1 到 5 之间的数字,它将启动到该运行级别(1 始终是单用户模式,其他是系统定义的,3 或 4 是大多数 Linux 发行版通常使用的默认值)。如果您使用的是 systemd,则可以在内核参数末尾传递single
或来分别启动到这些模式。emergency
然而,使用这种机制传递任意参数有点困难,因为内核执行绝对最少的解析,这特别意味着:
- 带有空格的参数根本无法传递,因为内核不会解析带引号的字符串(即被
'some string'
解析为两个参数'some
和string'
)。 - 您根本无法引用任何环境变量,因为内核不执行变量替换(这通常是由您运行命令的 shell 在启动命令之前完成的)。
- 一般来说,参数必须能够在 POSIX C 语言环境(本质上是 US ASCII)下正确解释,这会将国际化抛到了窗外,除非您想使用诸如 base64 或 punycode 之类的东西。
- 内核参数中可以传递的数据量有一个上限,但我忘记了它是什么。
这些限制加在一起就是为什么你在 Google 上找不到任何关于做此类事情的信息,没有一个头脑清醒的系统集成工程师会这样做,因为解决上述限制比仅仅编写脚本要付出更多的努力包含所有必需的参数并调用它。
答案2
内核从内核命令行解析参数到“
--
”;如果它无法识别参数并且不包含“.”,则该参数将传递给 init:带有“=”的参数进入 init 的环境,其他参数作为命令行参数传递给 init。 “--
”之后的所有内容都作为参数传递给 init。