Upstart 脚本:在启动时检测 Shift 键按下

Upstart 脚本:在启动时检测 Shift 键按下

我想创建一个启动潜力,允许根据启动时的特定按键(或组合)加载不同的 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,但可以拥有一组很好的静态作业,只需根据不同的启动信号执行即可。

相关内容