怎样实现超时强制终止脚本

wen 实用脚本 28

本文目录导读:

怎样实现超时强制终止脚本

  1. 使用 timeout 命令(Linux/macOS)
  2. 使用 alarm 信号(Bash 脚本)
  3. 使用 SIGALRMexpect
  4. 使用子进程和 wait
  5. 使用 Python(跨平台方案)
  6. 使用 TMOUT(Bash 特定)
  7. 防止脚本被轻易中断
  8. 推荐使用:

使用 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

使用 SIGALRMexpect

更复杂的超时控制:

#!/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 变量

选择哪种方法取决于你的具体需求和操作系统。

抱歉,评论功能暂时关闭!