为何Bash函数中的read命令会导致任务停止?
Bash
extdebug模式下子shell内read触发任务停止的行为解析 复现代码与环境
定义的Bash函数:
test1 () { ( touch /tmp/test1 rm /tmp/test1 read -rp "Enter anything: " anything echo "Anything: ${anything}" ) }
设置的陷阱与Shell选项:
trap 'echo trapped' DEBUG; shopt -s extdebug
使用的Bash版本:5.2.15(1)-release (aarch64-apple-darwin22.1.0)
执行现象
在交互式Bash会话中执行函数时,read语句会导致任务被暂停:
$ test1 () { ( touch /tmp/test1 rm /tmp/test1 read -rp "Enter anything: " anything echo "Anything: ${anything}" ) } $ test1 Enter anything: [1]+ Stopped ( touch /tmp/test1; rm /tmp/test1; read -p "Enter anything: " anything; echo "Anything: ${anything}" ) $ fg 1 ( touch /tmp/test1; rm /tmp/test1; read -p "Enter anything: " anything; echo "Anything: ${anything}" ) something Anything: something
关键现象:如果read命令前仅存在一个命令,函数可以正常执行,不会触发暂停。
行为原因解析
当开启extdebug选项时,Bash的DEBUG陷阱会在每个命令执行前触发。对于子shell中的多命令序列,Bash会将子shell进程标记为"需要调试跟踪",而在交互式会话的作业控制规则下,被跟踪的进程尝试读取终端输入时,会被内核发送SIGTTIN信号暂停——这和后台进程尝试读取终端时的行为一致。
具体细节:
extdebug模式下,DEBUG陷阱会触发Bash对每个命令的跟踪机制,子shell内命令数量≥2时,完整跟踪机制会被激活- 被跟踪的进程执行
read读取终端时,终端驱动会判定其不符合前台作业的读取权限,发送SIGTTIN信号导致进程暂停 - 若子shell内只有一个命令,Bash不会启用完整的跟踪标记,进程仍被视为前台作业,
read可正常读取终端输入
内容的提问来源于stack exchange,提问作者cementblocks
相关产品推荐
相关产品推荐

