You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bash脚本source执行时trap捕获INT信号失效问题求助

问题根因分析

这个现象的核心原因是source命令和直接执行脚本的运行模式差异,以及前台进程组的信号传递规则:

  • 直接执行./test2.sh时,系统会创建独立的Bash子进程运行脚本,脚本内注册的trap属于该子进程的信号处理规则。按下ctrl+c时,INT信号会发送给整个前台进程组(脚本子进程+sleep子进程),脚本子进程收到INT信号后就会触发绑定的ctrl_c回调函数,符合预期。
  • 通过source(即.命令)执行脚本时,脚本代码会直接在当前交互式Bash进程中执行,不会创建新的独立子进程。此时脚本里的sleep 500会作为当前shell的前台子进程运行,按下ctrl+c时,INT信号首先被sleep进程接收,sleep收到INT后直接终止退出,信号并不会传递给父级的当前交互式shell,因此你给当前shell注册的INT信号trap完全不会触发。
原理验证

你可以通过以下操作验证上述逻辑:

  1. 打开两个终端窗口,第一个终端执行echo $$拿到当前shell的PID,然后执行. test2.sh让脚本进入sleep状态
  2. 第二个终端执行kill -INT <第一步拿到的shell PID>,直接给当前运行source的shell进程发INT信号
  3. 回到第一个终端,可以看到trap正常触发,打印出user canceled.,说明trap本身注册是成功的,只是ctrl+c发送的信号被sleep进程拦截了。
兼容解决方案

如果需要脚本同时兼容直接运行和source运行时都能捕获ctrl+c,可以把单条sleep命令替换为「后台运行+wait」的写法,利用Bash内置命令wait会接收信号的特性触发trap:

#!/bin/bash

ctrl_c()
{                                                 
  echo "user canceled."                                    
}                                                          

trap ctrl_c INT

# 替换原sleep 500行
sleep 500 &
wait $!

trap - INT

修改后无论用哪种方式执行脚本,按下ctrl+c都能正常触发信号处理逻辑。


内容的提问来源于stack exchange,提问作者Dude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 19:36:03