Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux Bash脚本捕获信号,但随后等待进程终止_Linux_Bash_Signals - Fatal编程技术网

Linux Bash脚本捕获信号,但随后等待进程终止

Linux Bash脚本捕获信号,但随后等待进程终止,linux,bash,signals,Linux,Bash,Signals,目前我正在编写一个bash脚本,如下所示: foo(){ 虽然是真的 做 睡眠10 完成 } bar(){ 虽然是真的 做 睡20 完成 } 福& 酒吧& 等待 (我知道这样的剧本没有意义,只是结构而已) 现在我想用trap--RTMIN+1添加信号处理。一开始这是可行的。当脚本接收到rtmin+1信号时,它会做一些事情,但之后它就存在了(使用163退出代码,这是正在发送的信号的编号) 这不是我想要的行为。我希望在接收到信号后,脚本继续等待进程(在本例中是两个函数)终止(在本例中当然不会发生这

目前我正在编写一个bash脚本,如下所示:

foo(){
虽然是真的
做
睡眠10
完成
}
bar(){
虽然是真的
做
睡20
完成
}
福&
酒吧&
等待
(我知道这样的剧本没有意义,只是结构而已)

现在我想用
trap--RTMIN+1
添加信号处理。一开始这是可行的。当脚本接收到rtmin+1信号时,它会做一些事情,但之后它就存在了(使用163退出代码,这是正在发送的信号的编号)

这不是我想要的行为。我希望在接收到信号后,脚本继续等待进程(在本例中是两个函数)终止(在本例中当然不会发生这种情况,但脚本应该等待)

我尝试添加一个
;等待
接收信号时应该做的事情,但这没有帮助(或者我做错了什么)

有人知道如何达到期望的行为吗

提前感谢并致以最良好的祝愿

编辑:也许一个更精确的例子有助于:

clock(){
本地前缀=C
局部间隔=1
虽然是真的
做
printf“${prefix} $(日期'+%d.%m%H:%m:%S')\n
睡眠时间间隔
完成
}
卷(){
前缀=V
volstat=“$(amixer get Master 2>/dev/null)”
echo“$volstat”| grep“\[off\]”>/dev/null&&icon=”" #备选方案:聋人: 静音:
vol=$(echo“$volstat”| grep-o“\[[0-9]\+%\]”sed“s/[^0-9]*///g;1q”)
如果[-z“$icon”];则
如果[“$vol”-gt“50”];则
图标=”"
#elif[“$vol”-gt“30”];然后
#图标=”"
其他的
图标=”"
fi
fi
printf“${prefix}%s%3s%%\n”“$icon”“$vol”
}
钟&
卷&
陷阱--“卷”RTMIN+2
等待
现在,
RTMIN+2
信号应该重新运行
volume
功能,但是
时钟
过程不应该中断。(到目前为止,整个脚本(包括所有子过程)在接收到信号时终止)

重写了一些内容 为了避免一些无用的叉子

clock(){  local prefix=C interval=2
    trap : RTMIN{,+{{,1}{1,2,3,4,5},6,7,8,9,10}}
    while :;do
        printf "%s: %(%d.%m %H:%M:%S)T\n" $prefix -1
        sleep $interval
    done
}

volume(){  local prefix=V vol=() field playback val foo
    while IFS=':[]' read field playback val foo;do
        [ "$playback" ] && [ -z "${playback//*Playback*}" ] && [ "$val" ] &&
            vol+=(${val%\%})
    done < <(amixer get Master)
    suffix='%%'
    if [ "$vol" = "off" ] ;then
        icon="" #alternative: deaf:  mute: 
        suffix=''
    elif (( vol > 50 )) ;then  icon=""
    elif (( vol > 30 )) ;then  icon=""
    else                       icon=""
    fi
    printf -v values "%3s$suffix " ${vol[@]}
    printf "%s%s %s\n" $prefix "$icon" "$values"
}

clock & volume &

trap volume RTMIN+2
trap : RTMIN{,+{{,1}{1,3,4,5},6,7,8,9,10,12}}
echo -e "To get status, run:\n  kill -RTMIN+2 $$"

while :;do wait ;done

有关
wait
命令如何工作和良好实践的更多信息,请查看good

当在没有操作数的情况下调用时,
wait
0退出,这意味着调用shell已知的所有进程ID都已终止,或者值大于128,这意味着whi的信号接收到陷阱已设置。因此,循环直到
wait
0
退出足以在接收到信号后使脚本保持活动状态。您还可以检查其退出状态在循环中是否小于128,但我认为这没有必要

但是,如果您使用
pkill
发送这些信号,则在后台启动的作业也将接收这些信号,因为子进程从其父进程继承进程名称,而不是从自定义信号处理程序继承,并且
pkill
向名称匹配的所有进程发送信号。您也需要处理这种情况

一个最低限度的工作示例是:

#! /bin/bash -
# ignore RTMIN+1 and RTMIN+2 temporarily
# to prevent pkill from killing jobs
trap '' RTMIN+1 RTMIN+2

# start jobs
sleep 20 && echo slept for 20 seconds &
sleep 30 && echo slept for 30 seconds &

# set traps
trap 'echo received rtmin+1' RTMIN+1
trap 'echo received rtmin+2' RTMIN+2

# wait for jobs to terminate
until wait; do
  echo still waiting
done
还值得注意的是,在开始作业之前忽略
RTMIN+1
RTMIN+2
会阻止外壳从它们下降而捕获/重置这些信号。如果这是一个问题,您可以按照F.Hauri的建议在作业中设置一个空陷阱;或者您可以完全放弃忽略,并将
pkill
-o
一起使用选择将信号发送到最早的匹配进程

参考资料:

相关的:


尝试用
替换
等待
,while:;do wait;echo“V:$vol;done
这是你在回答中阐述的相同想法吗?是:
等待
将在接收到某个信号时终止。因此你必须循环。
echo“V:“$vol
可以帮助您查看执行时刻。您是否发送了
RTMIN+2
RTMIN+1
?我发送了
RTMIN+2
您能否详细说明一下这一点为什么有效,而前一个无效?您必须向主pid发送信号,而不是向时钟子进程发送信号!您的环境(操作系统、版本)是什么?您可以通过将
trap:
添加到
clock
子流程中来避免退出子流程。查看我的上一次编辑。我删除了echo…| grep…| sed…,替换为纯bash循环。(Nota
sed's/*\[\(off\\[0-9]\+\)%\?\]./\1/;ta;bb;:a;q;:b;d'有一些改进:尽可能使用整数测试,在立体声系统中打印左右音量,方法是将
$values
输出准备为单独的步骤。错误:立体声系统中只测试左输出:左=右=100%将失败(百分比符号将丢失,图标将错误)。
volume(){
    local prefix=V vol=() field playback val foo icons=(⏻ ¼ ¼ ¼ ½ ½ ¾ ¾ ¾ ¾ ¾)
    local -i overallvol=0
    while IFS=':[]' read field playback val foo ;do
        [ "$playback" ] && [ -z "${playback//*Playback*}" ] && [ "$val" ] && {
            vol+=($val)
            val=${val%\%}
            overallvol+=${val//off/0}
        }
      done < <(
        amixer get Master
    )
    overallvol=$overallvol/${#vol[@]}
    printf "%s%s %s\n" $prefix "${icons[(9+overall)/10]}" "${vol[*]}"
until wait;do :;done
#! /bin/bash -
# ignore RTMIN+1 and RTMIN+2 temporarily
# to prevent pkill from killing jobs
trap '' RTMIN+1 RTMIN+2

# start jobs
sleep 20 && echo slept for 20 seconds &
sleep 30 && echo slept for 30 seconds &

# set traps
trap 'echo received rtmin+1' RTMIN+1
trap 'echo received rtmin+2' RTMIN+2

# wait for jobs to terminate
until wait; do
  echo still waiting
done