本文目录导读:

- 使用
timeout命令(Linux/macOS) - 使用
alarm信号(Bash 脚本) - 使用
SIGALRM和expect - 使用子进程和
wait - 使用 Python(跨平台方案)
- 使用 TMOUT(Bash 特定)
- 防止脚本被轻易中断
- 推荐使用:
使用 timeout 命令(Linux/macOS)
最简单的内置方法:
# 超时 5 秒终止命令 timeout 5s long-running-command # 也可以使用其他时间单位 timeout 5 seconds timeout 1m # 1分钟 timeout 1h # 1小时 # 发送 SIGKILL 而不是默认的 SIGTERM timeout --signal KILL 5s long-running-command # 保留退出状态 timeout 5s command || echo "Command timed out with exit $?"
使用 alarm 信号(Bash 脚本)
利用 SIGALRM 信号:
#!/bin/bash
# 超时处理函数
timeout_handler() {
echo "ERROR: Script timed out"
kill -s SIGTERM $$ # 终止自身
exit 1
}
# 设置超时(单位:秒)
TIMEOUT=5
trap timeout_handler SIGALRM
( sleep $TIMEOUT; kill -s SIGALRM $$ ) &
# 脚本主要逻辑
while true; do
echo "Running..."
sleep 1
done
使用 SIGALRM 和 expect
更复杂的超时控制:
#!/bin/bash
# 设置超时
TIMEOUT=10
# 后台进程作为计时器
(sleep $TIMEOUT; kill -s ALRM $$ >/dev/null 2>&1) &
# 计时器 PID
TIMER_PID=$!
# 超时处理
trap 'echo "Timeout reached"; kill $TIMER_PID; exit 1' ALRM
# 你的脚本逻辑
echo "Starting long operation..."
# 模拟长时间运行
for i in {1..30}; do
echo "Processing $i..."
sleep 1
done
# 取消计时器
kill $TIMER_PID 2>/dev/null
使用子进程和 wait
#!/bin/bash
TIMEOUT=10
# 在子进程中运行主要逻辑
(
# 主要脚本逻辑
for i in {1..30}; do
echo "Working $i..."
sleep 1
done
) &
CHILD_PID=$!
# 启动计时器
(sleep $TIMEOUT; kill $CHILD_PID 2>/dev/null) &
TIMER_PID=$!
# 等待子进程完成或超时
wait $CHILD_PID
EXIT_CODE=$?
# 清理计时器
kill $TIMER_PID 2>/dev/null
if [ $EXIT_CODE -eq 0 ]; then
echo "Script completed successfully"
else
echo "Script terminated (timeout or error)"
fi
使用 Python(跨平台方案)
#!/usr/bin/env python3
import signal
import sys
import time
class TimeoutError(Exception):
pass
def timeout_handler(signum, frame):
raise TimeoutError("Script timed out")
# 设置 10 秒超时
TIMEOUT = 10
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(TIMEOUT)
try:
# 你的脚本逻辑
while True:
print("Running...")
time.sleep(1)
except TimeoutError:
print("Timeout reached, terminating...")
sys.exit(1)
finally:
signal.alarm(0) # 取消闹钟
使用 TMOUT(Bash 特定)
#!/bin/bash
# 设置读取超时(单位:秒)
TMOUT=5
# read 命令会在 TMOUT 后超时
echo "You have 5 seconds to respond:"
read -p "Enter something: " input
if [ -z "$input" ]; then
echo "Input timed out!"
else
echo "You entered: $input"
fi
防止脚本被轻易中断
如果你想防止用户通过 Ctrl+C 中断:
#!/bin/bash
# 忽略 SIGINT(Ctrl+C)和 SIGQUIT
trap '' SIGINT SIGQUIT
# 但保留超时功能
TIMEOUT=30
trap 'echo "Script timed out"; exit 1' SIGALRM
( sleep $TIMEOUT; kill -s ALRM $$ ) &
# 主要逻辑
while true; do
echo "Running (Ctrl+C disabled)..."
sleep 1
done
推荐使用:
- 简单情况:
timeout命令最方便 - 复杂脚本:信号机制更灵活
- 跨平台:Python 方案
- 交互式脚本:TMOUT 变量
选择哪种方法取决于你的具体需求和操作系统。