Linux timeout 命令完全指南:指定固定时间并发送固定信号
日常运维中,我们经常需要运行一些可能"卡住"的命令------压测脚本、爬虫、抓包工具、长任务进程。它们平时运行正常,但偶尔会因为网络抖动、死锁、等待输入等原因一直不退出 ,把终端或后台任务死死占住。这时候,timeout 命令就是最省心的"保险丝"。
一、timeout 能做什么
timeout 是 GNU coreutils 自带的一个命令,作用是:运行一个命令,若它在指定时间内没有结束,就向它发送一个信号,强制或优雅地把它终止。
它解决的核心痛点是:
- 命令卡死时能自动超时退出,不用人工 Ctrl+C
- 可以灵活指定"超时多久"、"到时发什么信号"
- 避免长任务无限期占用系统资源
二、基本语法
bash
timeout [选项] 持续时间 命令 [参数...]
其中"持续时间"就是超时阈值,后面的 命令 参数 是真正要执行的内容。
三、指定固定时间
时间可以直接写数字,也可以带后缀。默认单位是秒,后缀 s 表示秒、m 表示分钟、h 表示小时、d 表示天。
bash
# 10 秒(不带后缀默认秒)
timeout 10 mycmd
# 显式写 10 秒,更清晰
timeout 10s mycmd
# 5 分钟
timeout 5m mycmd
# 2 小时
timeout 2h mycmd
小提示:
timeout 10和timeout 10s是等价的。为了可读性,建议显式加上单位后缀。
四、指定固定信号
到点之后,timeout 默认发送 SIGTERM (信号 15)。我们可以用 -s / --signal= 指定到底发送哪种信号:
bash
# 到时发送 SIGINT(Ctrl+C 的等效信号,2 号)
timeout --signal=INT 10s mycmd
# 到时发送 SIGTERM(默认,15 号)
timeout --signal=TERM 10s mycmd
# 到时直接 SIGKILL(9 号,无法被捕获,立即强杀)
timeout -s KILL 10s mycmd
信号既可以写名称(INT、TERM、KILL),也可以写数字(2、15、9)。
常见的信号选择逻辑:
| 信号 | 数字 | 行为 | 适用场景 |
|---|---|---|---|
| SIGTERM | 15 | 优雅终止,进程可捕获并清理 | 默认选择,多数场景 |
| SIGINT | 2 | 相当于手动 Ctrl+C | 希望模拟用户中断 |
| SIGKILL | 9 | 立即强杀,无法被捕获 | 兜底,进程彻底不响应时 |
五、完整示例深度解读
你可能会在实际脚本里看到这样一条命令:
bash
timeout --signal=INT --kill-after=10s 10s \ ngauge /root/ngauge-test-20260929/config.yml
我们来拆解它的每一部分含义:
timeout:超时控制命令--signal=INT:到点时发送 SIGINT 信号,让 ngauge 优雅地收尾--kill-after=10s:发送 SIGINT 之后再给 10 秒缓冲时间10s:总共运行 10 秒,到时触发超时ngauge /root/ngauge-test-20260929/config.yml:实际要运行的命令及其参数
执行的完整时间线:
- 启动 ngauge,加载
config.yml开始压测 - 运行 10 秒后,
timeout向 ngauge 发送 SIGINT,通知它"该停了,自己清理" - 此时 ngauge 有机会保存数据、关闭连接、释放资源(不会立即被杀掉)
- 如果 ngauge 在 10 秒的缓冲期内正常退出,流程就顺利结束
- 如果 ngauge 收到 SIGINT 后 10 秒内仍然不死,
--kill-after触发,发送 SIGKILL 强制杀死
一句话总结 :这是非常经典的"先优雅后强制"的停止策略------给进程一次体面退出的机会,实在不行再动刀。
六、为什么这样设计很有用
很多服务类工具收到 SIGINT 后会做资源清理:比如压测工具要关闭网络连接、抓包工具要落盘保存数据、数据库客户端要提交事务。如果一上来就发 SIGKILL,这些数据可能直接丢失或损坏。
而 --kill-after 正好弥补了"发了优雅信号但进程仍卡死"的漏洞,保证一定能在某个时间点杀掉进程,不会无限期挂住。这对脚本、CI、定时任务里的防挂死处理特别有价值。
七、其他常用选项
timeout 还有几个实用的参数:
bash
# 超时后保留命令的退出码,方便脚本判断失败原因
timeout --preserve-status 10s mycmd
# 在前台模式下运行(配合管道使用,避免无法获取子进程输出)
timeout --foreground 10s cmd | tee log.txt
# 把超时时长作为第一个参数传给命令(少见,但存在)
timeout --timeout=10s mycmd
--preserve-status:超时杀掉命令后,返回 127 还是命令实际退出码由它决定,用于脚本精确判断"是超时了还是真出错了"。--foreground:当 timeout 和管道、后台作业一起用,无法往子进程发信号时使用。
八、总结
timeout 是一个小而美的命令,核心要素只有两个:
- 时间:告诉它"多久算超时"
- 信号:告诉它"超时后怎么处理"
再配合 --kill-after,就能实现"给机会、不无限等 "的优雅停止策略。下次再写压测、抓包或长任务脚本,别忘了给它上一道 timeout 保险丝。