Shell面试题 - Shell 脚本中如何使用trap命令捕捉和处理信号?


1. 信号概述

在 Unix/Linux 系统中,信号是进程间通信的一种机制,用于通知进程发生了某种事件。常见的信号包括:

信号编号 信号名称 说明
1 SIGHUP 终端挂断或控制进程终止
2 SIGINT 键盘中断 (Ctrl+C)
3 SIGQUIT 键盘退出 (Ctrl+)
9 SIGKILL 强制终止
15 SIGTERM 终止信号

2. trap 命令基本用法

trap 命令用于在 shell 脚本中捕获并处理信号,基本语法如下:

trap 'command' SIGNAL

示例 1:捕获 Ctrl+C (SIGINT)

#!/bin/bash

trap 'echo "You pressed Ctrl+C!"' SIGINT

echo "Press Ctrl+C to test"
sleep 10
echo "Done"
脚本开始
设置trap捕获SIGINT
输出提示信息
睡眠10秒
收到SIGINT?
执行trap命令
输出Done

3. 常见的 trap 使用场景

3.1 清理临时文件

#!/bin/bash

tempfile=$(mktemp)

cleanup() {
    echo "Removing temp file..."
    rm -f "$tempfile"
    exit
}

trap cleanup EXIT SIGINT SIGTERM

echo "Working with temp file: $tempfile"
# 模拟工作
sleep 10

3.2 忽略信号

#!/bin/bash

trap '' SIGINT  # 忽略SIGINT信号

echo "Try pressing Ctrl+C, it won't work now"
sleep 5
echo "Done"

3.3 重置信号处理

#!/bin/bash

trap 'echo "First trap"' SIGINT
sleep 2 & wait

trap 'echo "Second trap"' SIGINT  # 覆盖之前的处理
sleep 2 & wait

trap - SIGINT  # 重置为默认行为
sleep 2 & wait

4. Java 中的信号处理

虽然本文主要讨论 shell 脚本中的信号处理,但这里提供一个 Java 中处理信号的示例作为对比:

import sun.misc.Signal;
import sun.misc.SignalHandler;

public class SignalExample {
    public static void main(String[] args) {
        // 处理SIGINT (Ctrl+C)
        Signal.handle(new Signal("INT"), new SignalHandler() {
            public void handle(Signal sig) {
                System.out.println("Received SIGINT (Ctrl+C)");
                // 清理工作
                System.exit(0);
            }
        });

        System.out.println("Press Ctrl+C to test");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("Done");
    }
}
Java程序启动
注册信号处理器
输出提示信息
睡眠10秒
收到SIGINT?
执行信号处理逻辑
输出Done
退出程序

5. 高级用法

5.1 获取触发 trap 的信号

#!/bin/bash

handler() {
    echo "Caught signal $1"
}

trap 'handler SIGINT' SIGINT
trap 'handler SIGTERM' SIGTERM

echo "PID: $$"
sleep 10

5.2 在函数中使用 trap

#!/bin/bash

setup() {
    trap 'echo "Exit signal caught"; exit' EXIT
    echo "Trap set in setup function"
}

setup
echo "Main script running"
sleep 2

6. 注意事项

  1. SIGKILLSIGSTOP 不能被捕获、阻塞或忽略
  2. trap 命令的作用范围是当前的 shell 进程
  3. 子进程默认不会继承父进程的信号处理方式
  4. 在函数中设置的 trap 会影响整个脚本

7. 总结

trap 命令是 shell 脚本中处理信号的强大工具,可以用于:

  • 优雅地处理脚本中断
  • 执行清理操作
  • 忽略特定信号
  • 自定义信号处理行为

合理使用 trap 可以使脚本更加健壮和可靠。

信号产生
是否被trap捕获?
执行trap命令
执行默认操作
继续执行脚本
可能终止脚本
Logo

一站式 AI 云服务平台

更多推荐