如何实现暂停系统启动进程并获取控制台输入后继续启动?
嘿,这个需求其实和加密磁盘解锁的逻辑异曲同工——核心就是让你的程序卡在关键系统服务启动之前,并且硬生生把启动流程按住,直到用户完成输入才放行。既然你会C/C++,那咱们一步步来拆解怎么实现:
普通的启动脚本(比如/etc/init.d或者systemd的用户级服务)大多是异步启动的,系统会自顾自往下跑其他服务,根本不会等你的程序结束。你需要的是一个同步阻塞的启动单元,让系统必须等你的程序退出后,才敢继续启动后续服务。
针对主流systemd系统(大部分Linux发行版)
这是当前最常见的场景,咱们重点讲这个:
1. 写你的C/C++交互程序
这个程序逻辑很简单:在控制台输出提示,读取用户输入,验证通过后正常退出(验证失败可以选择终止启动)。注意要适配纯控制台环境(启动阶段还没图形界面),直接用标准输入输出就行,示例代码:
#include <iostream> #include <string> int main() { // 确保输出直接刷到控制台,避免缓冲导致看不到提示 std::cout << "请输入确认指令以继续启动系统:" << std::endl << std::flush; std::string input; std::getline(std::cin, input); // 这里加你的自定义验证逻辑 if (input != "unlock-system") { std::cerr << "指令错误,系统将停止启动" << std::endl << std::flush; return 1; // 返回非0码,让系统启动失败 } std::cout << "验证通过,系统继续启动..." << std::endl << std::flush; return 0; }
编译后把程序放到/usr/local/bin/(比如命名为startup-blocker),给执行权限:
chmod +x /usr/local/bin/startup-blocker
2. 创建systemd服务单元
你需要写一个oneshot类型的服务配置,告诉systemd:这个程序必须同步执行完,而且要在所有核心服务启动前跑。
在/etc/systemd/system/下创建startup-blocker.service文件,内容如下:
[Unit] Description=System Startup Confirmation Prompt # 确保这个服务在多用户模式(核心服务启动阶段)之前运行 Before=multi-user.target # 可选:设置为必需项,启动失败则整个系统启动终止 Requires=startup-blocker.service # 指定用第一个控制台来交互 ConsoleTTY=tty1 [Service] Type=oneshot # 你的程序路径 ExecStart=/usr/local/bin/startup-blocker # 前台运行,阻塞启动流程 RemainAfterExit=no # 绑定控制台的标准输入输出,不然看不到提示也输不了内容 StandardInput=tty StandardOutput=tty StandardError=tty [Install] WantedBy=multi-user.target
3. 启用服务让它生效
执行以下命令刷新systemd配置并启用服务:
systemctl daemon-reload systemctl enable startup-blocker.service
下次重启系统时,你就会看到控制台弹出输入提示,输入正确后系统才会继续启动后续服务。
针对老版本SysVinit系统
如果你的系统还在用SysVinit(比如某些老的CentOS、Debian版本),那就直接修改启动脚本:
找到/etc/rc.d/rc.sysinit(不同系统路径可能有差异),在挂载文件系统之后、启动其他服务之前的位置,添加对你程序的调用:
# 调用你的C/C++程序,同步执行(不要加&后台运行) /usr/local/bin/startup-blocker # 如果程序返回非0,终止启动 if [ $? -ne 0 ]; then echo "启动验证失败,系统将停止" halt fi
这样系统启动到这个步骤时,就会停下来等你的程序执行完。
几个关键注意事项
- 权限问题:启动阶段的程序是以root身份运行的,要注意程序的安全性,避免输入被窃取或者恶意利用。
- 终端适配:如果你的程序需要特殊的终端功能,要确保启动阶段的tty环境支持(比如避免用ncurses这类复杂库,除非你确认依赖都已加载)。
- 测试建议:先在虚拟机里测试,别直接在物理机上折腾,万一搞坏启动流程就麻烦了。
内容的提问来源于stack exchange,提问作者Lieuwe

