我想创建一个启动潜力,允许根据启动时的特定按键(或组合)加载不同的 upstart/运行级别配置。如何使用 upstart 脚本检测按键事件?
如果有帮助的话,我在 10.04。
可以使用替代方法来达到相同的结果,即,如何使用 grub 来做到这一点?
为了提供更清晰的解释,我根据 Tuminoid 和 Lumbric 给出的答案创建了分步说明。(请帮助我改进这一点,我对 Tuminoid 答案的解释不起作用。)
笔记:每个人这样做肯定都有原因。为了使以下两个分步解决方案有意义,我将描述我希望在启动时决定 upstart 脚本的目的。
我正在创建一个名为 Surfer 的用于上网的 Live DVD。出于安全考虑,我想禁用管理员帐户并保留一个非特权帐户用于上网。我还想让我自己和用户能够重新制作 Surfer,以便他们可以添加更多在线应用程序并自定义他们的 Surfer 帐户,然后刻录他们自己的实时自定义 Surfer iso。所以我需要两个启动配置文件:Surfer 和 Remaster。一个用于安全在线浏览,另一个用于重新制作和开发。
Lumbric 的解决方案
创建自定义 grub 文件
1. 要向 grub 添加自定义条目,请使用 gedit 打开此文件进行编辑:
gksudo gedit /etc/grub.d/40_custom
如果你看到以下文本,则表示你拥有正确的文件:
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
2. 在另一个 gedit 选项卡中,打开:
/boot/grub/grub.cfg
3. 在 grub.cfg 中,查找以以下内容开头的部分:
菜单项
选择用于启动的默认条目。如果您通过查看此文件不知道默认条目,请重新启动并记下您在启动时选择的条目。 如果必须重新启动才能找到默认条目,请不要保存任何更改。 当您对默认条目感到确定时,请注意这是用于自定义配置文件的条目。
每个菜单项部分将有一些相应的括号:
menuentry ...text left out... { ...text left out... }
封装几行文本。复制您的默认条目部分。从 word 中复制菜单项到结束括号。我需要两个条目,所以我将粘贴我的默认条目两次。
对于两个自定义启动配置文件条目,它看起来应该类似于以下内容。(请记住,我删除了文本以使其更易于阅读):
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
menuentry ...text left out... {
...text left out...
}
menuentry ...text left out... {
...text left out...
}
4. 按 ctrl + f 找到您的启动行。在搜索字段中输入:
Linux /启动
每个引导行都应被突出显示。
5. 将此文本剪切并粘贴到突出显示的引导行的末尾,但更改每个条目的数字。
启动配置文件=1
粘贴后,菜单项应类似于此:
menuentry ...text left out... {
...text left out...
linux /boot/vmlinuz-2.6.35-22-generic root=UUID=66cdrfwec91-0070-32f-b666-c9f2232j23232j ro quiet splash boot-profile=1
}
menuentry ...text left out... {
...text left out...
linux /boot/vmlinuz-2.6.35-22-generic root=UUID=66cdrfwec91-0070-32f-b666-c9f2232j23232j ro quiet splash boot-profile=2
}
6. 现在,我们将编辑启动时看到的行。对于上面标识的菜单项,编辑单词 menuentry 和第一个括号之间的文本。用文本替换冲浪者:
menuentry "Surfer" {
...text left out...
linux /boot/vmlinuz-2.6.35-22-generic root=UUID=66cdrfwec91-0070-32f-b666-c9f2232j23232j ro quiet splash boot-profile=1
}
对 Remaster 条目执行相同操作:
menuentry "Remaster" {
...text left out...
linux /boot/vmlinuz-2.6.35-22-generic root=UUID=66cdrfwec91-0070-32f-b666-c9f2232j23232j ro quiet splash boot-profile=2
}
7. 保存文件 40_custom。
8.现在,使用以下命令更新 grub:
sudo update-grub
注意:如果您升级或安装了任何会修改内核的程序,请注意 lumbric 在其链接中提出的观点。我们如何知道我们的内核是否要升级?帮我解释一下如何防止在不知情的情况下升级内核。
9. 重启。在启动菜单中,查找新条目。如果看到它们,则表示一切正常。选择其中一个自定义条目并按 Enter 键。
10.登录后,打开终端。输入此命令。
猫/ proc /命令
Grub 写入引导行到这个文件。引导行是您在末尾添加 boot-profile=1 的地方。因此,如果您选择了 surfer,那么末尾应该显示 boot-profile=1,如果您选择了 Remaster,则末尾应该显示 boot-profile=2。如果不是,请从第一步重新阅读并纠正任何逻辑错误。
11. 现在,必须编写脚本来处理从 grub 菜单中选择的启动项。我选择使用 upstart 脚本,因为我知道如何执行此操作。upstart 将尽快启动,检查 /proc/cmdline 的内容并使用它来确定我们在启动菜单中的选择。以下是 upstart 启动脚本:
/etc/bootChoice.conf
12. 输入以下文本:
task
start on startup or bootChoice
script
profile=$(cat /proc/cmdline |sed 's/.*boot-profile=\([0-9]\).*/\1/g')
case $profile in
1)
# Run script for Surfer Profile
initctl emit surferboot
;;
2)
# Run script for Remaster Profile
initctl emit remasterboot
;;
*)
echo Error
echo "Error" > /error
;;
esac
end script
13.现在,将根据我们的选择发出一个信号。为了处理每个信号,必须创建两个文件。一个名为:surfer.conf,另一个名为 remaster.conf。将它们放在 /etc/init/ 中。它们的内容将类似于以下内容:
# surfer user boot
task
start on surferboot
script
echo "surfer test-data" > /home/surfer/surfer
end script
我们可以看到,当发出 surferboot 信号时,上面的脚本将根据以下行启动:start on surferboot
将所有自定义启动脚本代码放在 和 之间script
。Remasterend script
将执行相同的操作。
我试过了,有效。谢谢 Lumbric。
Tuminoid 的解决方案
首先,我们必须让 grub 知道我们想要调用一个脚本。我们将脚本的路径放在 /etc/default/grub 中。
1.打开文件:/etc/default/grub。
gksudo gedit /etc/default/grub
2.在文件末尾添加此行:
初始化=/sbin/preinit
3.保存并退出。然后运行以下命令:
更新 grub
现在我们将创建 grub 知道的文件。
4. 使用 gedit 创建文件:
gksudo gedit /sbin/preinit
5. 粘贴以下文本:
#!/bin/sh EVENT="startup" while [ /bin/true ]; do echo "Select boot:" echo " 1) Surfer" echo " 2) Remaster" echo "" read selection case "$selection" in 1) EVENT="surfer" ;; 2) EVENT="remaster" ;; *) ;; esac done exec /sbin/init --startup-event=$EVENT
6.使脚本可执行:
chmod + x /sbin/preinit
WIP 注:到目前为止,我已尝试过此方法,但不起作用。请指出我的错误之处,帮助改进对答案的解释。
最后部分: 此部分未完成。等待澄清第一步后再完成。
上述事件是 upstart 信号。如果您还没有使用过 upstart 信号,它们将调用目录中的脚本:/etc/init。因此,我将在 /etc/init 中创建两个文件,分别名为:
/etc/init/surfer.conf
/etc/init/remaster.conf
在这些文件中,我将使用 bash 脚本来配置每次启动。
如果选择了 Surfer,我将在 upstart /etc/gdm/custom.conf 中创建以强制自动登录。我还将打开 /etc/shadow 并禁用重新设置密码。
或者,我将创建 /etc/gdm/custom.conf 以强制用户 remaster 自动登录以进行重新制作和开发。
答案1
在启动过程中捕获 Shift 键按下事件似乎是一项有趣的任务,但我不知道如何实现这一点。但我在最近的问答如何使用 GRUB 菜单以便在登录后运行不同的启动脚本。
步骤 3 中的脚本旨在登录后运行,但也可以放在中/etc/rcXY
。
答案2
您无法对 Upstart 脚本执行此操作。它们本质上是非交互式的。
您可以做的是创建一个 Grub 菜单项,该菜单项指向一个 shell 脚本作为 init,提示您输入所需的启动类型(或以您喜欢的任何方式与您交互),然后在最后执行exec /sbin/init --startup-event=<type of boot>
。这会导致 Upstart 的启动事件不同于startup
,您可以将启动构建为任何您喜欢的启动。
例如,将如下内容放入/sbin/preinit
:
#!/bin/sh
EVENT="startup"
while [ /bin/true ]; do
echo "Select boot:"
echo " 1) Normal"
echo " 2) Minimal"
echo " 3) Foobar"
echo ""
read selection
case "$selection" in
2)
EVENT="minimal-startup"
;;
3)
EVENT="foobar-startup"
;;
*)
;;
esac
done
exec /sbin/init --startup-event=$EVENT
使用此解决方案,您不需要复制 /etc/init,但可以拥有一组很好的静态作业,只需根据不同的启动信号执行即可。