linux timeout命令

timeout命令 用于在指定的时间后终止命令的执行。它可以为任何命令设置执行时间限制,防止长时间运行或无响应的命令占用系统资源,是编写健壮脚本和自动化任务的重要工具。

命令格式

timeout [选项] 时间 命令 [参数]

常用选项

选项 说明
-k, --kill-after=时间 在指定时间后发送KILL信号(如果进程仍未终止)
-s, --signal=信号 指定要发送的信号(默认为TERM)
--preserve-status 返回子进程的退出状态(即使超时)
--foreground 在前台执行命令(当timeout不是从终端运行时)
-v, --verbose 详细输出模式
--help 显示帮助信息
--version 显示版本信息

时间格式说明

格式 示例 说明
秒数 10 10秒
分钟秒数 2m30s 2分钟30秒
小时分钟秒数 1h5m10s 1小时5分钟10秒
带单位缩写 5m, 2h, 30s 分钟、小时、秒
浮点数 0.5, 1.5 0.5秒、1.5秒
无限 0 不设置超时限制

信号说明

常用信号
  • SIGTERM (15) - 优雅终止(默认)
  • SIGKILL (9) - 强制终止
  • SIGHUP (1) - 挂起信号
  • SIGINT (2) - 中断信号(Ctrl+C)
使用建议
  • 先用TERM信号,给进程清理机会
  • 再用KILL信号,确保进程终止
  • 结合-k选项使用双重保障
  • 测试不同信号对应用的影响

使用实例

1. 基本用法:限制命令执行时间
# 限制ping命令最多执行5秒
timeout 5 ping -c 10 google.com

# 限制命令执行1分钟
timeout 1m ./long_running_script.sh
2. 指定发送的信号
# 5秒后发送KILL信号
timeout -s KILL 5 ./script.sh

# 使用信号编号
timeout -s 9 5 ./script.sh  # SIGKILL

# 发送SIGHUP信号
timeout -s HUP 30 ./daemon.sh
3. 双重超时保护(-k选项)
# 5秒后发送TERM信号,如果10秒后仍在运行则发送KILL
timeout -k 10 5 ./problematic_command.sh

# 使用不同时间单位
timeout -k 2m 1m ./command.sh  # 1分钟后TERM,2分钟后KILL
4. 详细输出模式
# 显示超时执行的详细信息
timeout -v 10 sleep 15

# 输出示例:
# timeout: sending signal TERM to command 'sleep'
# timeout: sending signal KILL to command 'sleep'
5. 保留退出状态
# 即使超时,也返回命令的实际退出状态
timeout --preserve-status 5 ./script.sh

# 在脚本中检查退出状态
timeout --preserve-status 10 ./task.sh
EXIT_STATUS=$?
echo "退出状态: $EXIT_STATUS"
6. 前台执行模式
# 确保命令在前台执行(适用于后台任务)
timeout --foreground 30 ./interactive_tool.sh
7. 复杂命令和管道
# 对管道中的命令设置超时
timeout 5 sh -c 'ls -la | grep "\.txt$"'

# 带参数的命令
timeout 10 find / -name "*.log" -type f

# 多命令组合
timeout 30 bash -c 'command1 && command2 || command3'
8. 在脚本中使用timeout
#!/bin/bash
# 超时执行数据库备份
echo "开始数据库备份..."

if timeout 300 mysqldump -u root -p'password' database > backup.sql; then
    echo "备份成功完成"
else
    EXIT_STATUS=$?
    if [ $EXIT_STATUS -eq 124 ]; then
        echo "备份超时(超过5分钟)"
    elif [ $EXIT_STATUS -eq 137 ]; then
        echo "备份被强制终止(KILL信号)"
    else
        echo "备份失败,退出状态: $EXIT_STATUS"
    fi
fi
9. 网络操作超时控制
# 限制wget下载时间
timeout 30 wget http://example.com/large_file.zip

# 限制curl请求时间
timeout 10 curl -I https://example.com

# 限制ssh连接时间
timeout 60 ssh user@remote-server "ls -la"
10. 无限超时(特殊情况)
# 使用0表示无限超时(不推荐,但有时有用)
timeout 0 ./never_ending_process.sh

实际输出示例

示例1:命令正常完成(未超时)
$ timeout 10 sleep 5
$ echo $?
0

命令在5秒内完成,正常退出,返回状态为0。

示例2:命令超时被终止
$ timeout 5 sleep 10
$ echo $?
124

sleep命令需要10秒,但在5秒时被终止,返回状态124(超时)。

示例3:使用详细模式
$ timeout -v 3 sleep 5
timeout: sending signal TERM to command 'sleep'
timeout: sending signal KILL to command 'sleep'
示例4:双重超时保护
$ timeout -k 3 2 sleep 10
# 2秒后发送TERM信号,3秒后发送KILL信号
$ echo $?
137  # 被KILL信号终止

退出状态码

退出码 说明 常见场景
0 命令在超时前成功完成 命令正常执行完毕
124 命令因超时被终止 命令执行时间超过限制
125 timeout命令自身失败 无效选项、无法执行命令等
126 找到命令但无法执行 权限不足、不是可执行文件
127 未找到命令 命令不存在或路径错误
137 命令被KILL信号终止 使用SIGKILL或-k选项
其他 命令自身的退出状态 命令执行失败(使用--preserve-status时)

实用场景

资源保护
  • 防止脚本无限循环
  • 限制资源密集型操作
  • 防止内存泄漏进程
  • 控制CPU占用时间
网络操作
  • 限制网络请求时间
  • 控制下载/上传超时
  • 防止网络阻塞
  • API调用超时处理
自动化脚本
  • 定时任务超时控制
  • 批处理作业管理
  • 系统监控脚本
  • 自动化测试
系统管理
  • 备份操作时间限制
  • 数据库查询超时
  • 服务启动超时控制
  • 维护操作时间窗口

实用命令组合

# 监控命令执行时间并记录日志
timeout 60 ./script.sh 2>&1 | tee execution.log

# 循环尝试直到成功(带超时)
for i in {1..3}; do
    echo "尝试第 $i 次..."
    if timeout 10 ./flaky_command.sh; then
        echo "成功!"
        break
    else
        echo "失败,等待重试..."
        sleep 5
    fi
done

# 并行执行多个命令,每个都有超时限制
(timeout 30 task1.sh) &
(timeout 45 task2.sh) &
(timeout 60 task3.sh) &
wait

# 超时执行并发送通知
if timeout 300 ./backup.sh; then
    echo "备份完成" | mail -s "备份成功" admin@example.com
else
    EXIT_CODE=$?
    echo "备份失败,退出码: $EXIT_CODE" | mail -s "备份失败" admin@example.com
fi

实际脚本示例

示例1:安全的数据库操作脚本
#!/bin/bash
# 安全的数据库维护脚本

DB_HOST="localhost"
DB_USER="admin"
DB_NAME="production_db"
BACKUP_DIR="/backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

echo "开始数据库维护..."

# 1. 备份数据库(最多10分钟)
echo "备份数据库..."
if timeout 10m mysqldump -h $DB_HOST -u $DB_USER -p'password' $DB_NAME > \
    $BACKUP_DIR/backup_$TIMESTAMP.sql; then
    echo "备份成功"
else
    BACKUP_EXIT=$?
    if [ $BACKUP_EXIT -eq 124 ]; then
        echo "错误:备份超时(超过10分钟)"
        exit 1
    else
        echo "错误:备份失败,退出码: $BACKUP_EXIT"
        exit 1
    fi
fi

# 2. 优化数据库(最多5分钟)
echo "优化数据库..."
if timeout 5m mysql -h $DB_HOST -u $DB_USER -p'password' $DB_NAME \
    -e "OPTIMIZE TABLE important_table"; then
    echo "优化成功"
else
    echo "警告:数据库优化超时或失败,但继续执行..."
fi

# 3. 清理旧数据(最多15分钟)
echo "清理旧数据..."
if timeout 15m mysql -h $DB_HOST -u $DB_USER -p'password' $DB_NAME \
    -e "DELETE FROM logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)"; then
    echo "清理成功"
else
    echo "错误:数据清理超时"
    exit 1
fi

echo "数据库维护完成!"
示例2:网络服务健康检查脚本
#!/bin/bash
# 网络服务健康检查脚本

SERVICES=(
    "http://api.example.com/health:5"
    "http://web.example.com:10"
    "tcp://db.example.com:3306:3"
    "https://auth.example.com:8"
)

echo "=== 服务健康检查 $(date) ==="

for SERVICE in "${SERVICES[@]}"; do
    # 解析服务配置
    URL=$(echo $SERVICE | cut -d: -f1-2)
    TIMEOUT=$(echo $SERVICE | cut -d: -f3)

    echo -n "检查 $URL (超时: ${TIMEOUT}s)... "

    if [[ $URL == http* ]]; then
        # HTTP/HTTPS检查
        if timeout $TIMEOUT curl -f -s -o /dev/null $URL; then
            echo "✓ 正常"
        else
            EXIT_CODE=$?
            if [ $EXIT_CODE -eq 124 ]; then
                echo "✗ 超时"
            else
                echo "✗ 失败 (退出码: $EXIT_CODE)"
            fi
        fi
    elif [[ $URL == tcp://* ]]; then
        # TCP端口检查
        HOST_PORT=$(echo $URL | sed 's/tcp:\/\///')
        if timeout $TIMEOUT bash -c "cat < /dev/null > /dev/tcp/${HOST_PORT/\// } 2>/dev/null"; then
            echo "✓ 正常"
        else
            echo "✗ 失败"
        fi
    fi
done

echo "=== 检查完成 ==="
注意事项:
  • timeout不能保证立即终止进程,某些进程可能忽略TERM信号
  • 使用-k选项提供双重保护,确保进程最终被终止
  • 子进程可能不会被timeout终止,使用进程组或更复杂的方法处理
  • 交互式命令可能需要--foreground选项
  • 某些命令(如shell内建命令)可能需要通过sh -c包装
  • 退出状态124表示超时终止,这在脚本中是一个有用的判断条件
  • 在生产环境中使用前,充分测试超时时间设置

timeout与其他方法对比

方法 优点 缺点 适用场景
timeout命令 简单直接,功能丰富,支持信号控制 可能无法终止所有子进程 大多数命令行超时需求
shell内置超时 无需外部命令,执行快 功能有限,语法复杂 简单脚本,兼容性要求高
expect脚本 功能强大,支持交互 需要额外安装,学习曲线陡 复杂的交互式会话
编程语言(Python等) 灵活可控,功能完整 需要编程知识,依赖运行环境 复杂的应用程序逻辑

安装timeout

timeout命令通常包含在coreutils软件包中,大多数Linux发行版默认已安装。

# 检查是否已安装
which timeout
timeout --version

# Ubuntu/Debian安装(如果需要)
sudo apt-get install coreutils

# CentOS/RHEL/Fedora安装
sudo yum install coreutils

# 验证安装
timeout --help

相关命令

sleep

延迟执行指定时间

查看详情
kill

发送信号终止进程

查看详情
at

定时执行命令

查看详情