如何在Rust中忽略SIGHUP信号
在Rust中忽略SIGHUP信号,让程序脱离终端后持续运行
实现思路
当终端关闭时,系统会向关联进程发送SIGHUP信号,默认行为是终止进程。要让程序继续运行,只需通过signal-hook crate注册一个空的SIGHUP信号处理逻辑,直接忽略该信号即可。
示例:后台秒数写入工具
下面是一个完整的实用示例——程序每秒向文件写入累计运行秒数,关闭终端后依然会持续运行,直到手动用kill命令终止。
首先在Cargo.toml中添加依赖:
[dependencies] signal-hook = "0.3"
然后编写src/main.rs:
use std::fs::OpenOptions; use std::io::Write; use std::thread; use std::time::Duration; use signal_hook::{consts::signal::SIGHUP, iterator::Signals}; fn main() -> std::io::Result<()> { // 注册SIGHUP信号监听,收到后不做任何处理(忽略信号) let mut signals = Signals::new(&[SIGHUP])?; thread::spawn(move || { for _ in signals.forever() { // 空逻辑,直接忽略SIGHUP信号 } }); // 打印进程ID,方便后续手动终止程序 println!("程序启动,进程ID:{}", std::process::id()); // 以追加模式打开目标文件,不存在则创建 let mut file = OpenOptions::new() .create(true) .append(true) .open("run_log.txt")?; let mut seconds = 0; loop { seconds += 1; writeln!(file, "已运行 {} 秒", seconds)?; file.flush()?; // 强制写入磁盘,避免缓存丢失 thread::sleep(Duration::from_secs(1)); } }
关键细节说明
- 信号处理:通过
Signals::new创建SIGHUP信号监听器,在子线程中循环接收信号但不执行任何操作,等价于忽略该信号,避免进程被终端关闭触发的SIGHUP终止。 - 文件写入:使用追加模式打开文件,每次写入后调用
flush()确保内容立即落盘,防止程序意外终止时数据滞留在缓存中。 - 验证方式:启动程序后关闭终端,查看
run_log.txt文件,会发现内容仍在持续更新,说明程序已在后台正常运行。
额外提示
- 如果需要同时忽略其他终端信号(比如Ctrl+C触发的SIGINT),可以在
Signals::new的参数中添加SIGINT,同样用空逻辑处理即可。 - 也可以结合
nohup命令启动程序,但通过代码忽略SIGHUP的方式更灵活,无需依赖外部命令。
内容的提问来源于stack exchange,提问作者Андрей Бабкин
相关产品推荐
相关产品推荐

