为什么 ERR 无权访问全局变量

时间:2021-06-19 18:57:01

标签: bash shell asynchronous

我有最简单的异步执行情况(在后台运行):

#!/bin/bash
# set-eE.sh

set -eE  # same as: `set -o errexit -o errtrace`

# global variable
PID=

# handle errors
trap errorfunc ERR
errorfunc(){
    echo "error PID=$PID"
}

function func(){
  cd nowhere
}

echo "func point"
func &
PID=$!
wait
echo "exit point PID=$PID"

不明白为什么我有下一个输出(注意PID下的空trap):

func point
./set-eE.sh: line 16: cd: nowhere: No such file or directory
error PID=
exit point PID=5464

所以,有两个问题:

  1. 为什么全局变量 PIDtrap errorfunc ERR 下为空
  2. 为什么我的脚本不会停止并一直运行到最后? 谢谢你。

1 个答案:

答案 0 :(得分:1)

总的来说,进程不是线程。 & 创建一个子进程,该子进程具有创建时的父 shell 执行环境的副本。在子环境中看不到在创建子环境后对父 shell 所做的更改 - 这些是单独的进程。

<块引用>

为什么 ERR 无法访问全局变量

它可以访问自己的全局变量并且它是空的,由PID=设置。

<块引用>

trap errorfunc ERR下为什么全局变量PID为空

因为它被 PID= 设置为空。

<块引用>

为什么我的脚本不会停止并一直运行到最后?

主 shell 进程不会停止,因为没有命令触发 set -e 在父 shell 中 - 所有命令都以 0 退出状态退出。


<块引用>

我需要脚本在引发 (func &) 任何 ERR 后停止其工作

然后从子shell中杀死父shell。作为一个快速而肮脏的黑客,您可以杀死进程组。

trap 'kill 0' ERR

更好的解决方案是杀死父母

parent=$BASHPID
{ 
    trap 'kill $parent' EXIT
    func
} &

您也可以专门等待子wait $PID,因为子以非零退出状态退出,将返回非零退出状态,这反过来会触发ERR陷阱父壳。

<块引用>

我需要杀死所有分叉的子shell

然后你必须将上下文转移到父 shell 并在那里进行杀戮。你可以前。将 SIGUSR1 发送到父 shell 并杀死父 shell 中的所有子进程(或者您可以杀死父 shell 并杀死父 shell 的 EXIT 陷阱中的所有子进程)。子进程不知道父进程是否存在其他子进程,因此必须先通知父进程被杀。

this unix thread。进程与shell环境、进程间通信与进程组研究。