gpt4 book ai didi

bash - 了解bash信号处理

转载 作者:行者123 更新时间:2023-12-03 02:30:11 25 4
gpt4 key购买 nike

前言

我最初的意图是编写一个脚本,该脚本每隔1秒检查一次播放Spotify音乐(耳机,立体声等...)的硬件(也许是沉没的术语?),这样即使终止Spotify,该信息还是可靠的(例如,这是Spotify关闭时使用的硬件的ID)。

我最初编写该脚本的目的实质上是一个脚本,该脚本调用并解析pactl list循环中的while true来检索Spotify在其上播放音频的硬件的#id。

只要Spotify处于启动状态,此方法就起作用,但是当Spotify关闭时,“监听器”的最终结果是一个空字符串,如果关闭Spotify后将pactl info称为,这对我来说似乎可以,但我认为我在打电话它是之前的

在这一点上,我想我可能误解了trap中信号处理和bash的工作方式。

M(非)WE

为了给自己和您一个MWE,我提出了以下建议。

  • 一个driver.sh脚本,该脚本在后台启动listener.sh脚本,然后在后台不在后台启动Spotify (我的理解是,向Spotify发送信号,例如将其关闭,会导致信号发送到driver.sh);它还设置了trap来终止后台进程。
  • #!/bin/bash
    trap 'kill -TERM $bg_pid' SIGINT SIGTERM EXIT
    ./listen.sh &
    bg_pid=$!
    echo "bg_pid: $bg_pid"
    /usr/bin/spotify
  • 一个listener.sh脚本,它在pactl list循环中无限解析media.name行的while true输出; trap确保解析在终止时最后一次发生。
  • #!/bin/bash
    trap 'echo trap:; func; exit' SIGINT SIGTERM EXIT
    func() {
    echo func: $(pactl list | sed -E '/media\.name/p;d')
    }
    while true; do
    func
    sleep 1
    done

    我认为,鉴于此设置,从终端中提取driver.sh将导致以下结果。
  • Spotify打开,终端被填充,
  • 形式的行
    func: media.name = "Spotify"
    func: media.name = "Spotify"
    func: media.name = "Spotify"
    ...
  • 关闭Spotify后(通过杀死driver.sh或关闭Spotify窗口),还有另外两行:
  • trap:
    func: media.name = "Spotify"

    相反,如果我关闭Spotify,我得到的是
    ...
    func: media.name = "Spotify"
    func: media.name = "Spotify"
    +enrico:~$ trap:
    func: # empty!
    trap:
    func: # why again?

    相反,如果我按CTRL + C driver.sh我得到了(评论是我的):
    ...
    func: media.name = "Spotify"
    func: media.name = "Spotify"
    ^Cfunc: media.name = "Spotify" # here I hit ctrl+c
    func: media.name = "Spotify" # maybe this delay is because of sleep in listener.sh?
    ./spot.sh: line 6: 8704 Segmentation fault (core dumped) /usr/bin/spotify # why this SegV?
    +enrico:~$ trap:
    func: # empty!
    trap:
    func: # why again?

    这让我感到困惑。我以为,收到终止信号后,driver.sh应该用trap捕获它并运行kill -TERM $bg_pid命令来处理它。反过来,listener.sh在接收到信号后应执行echo,然后执行func,然后执行exit。仅在这一点上,Spotify才能终止。如果在此之后调用pactl list将没有Spotify,我将理解。

    显然我可能误会了整个事情。

    最佳答案

    /usr/bin/spotify接收SIGINT并在driver.sh终止listen.sh终止之前死亡,因此pactl的空输出。您应该在后台运行/usr/bin/spotify,并在终止listen.sh之后终止它。

    因此,您的脚本应如下所示:

    driver.sh

    #!/bin/bash
    trap 'kill -TERM $bg_pid $!' SIGINT SIGTERM
    ./listen.sh &
    bg_pid=$!
    echo "bg_pid: $bg_pid"
    /usr/bin/spotify &
    wait

    listen.sh
    #!/bin/bash
    trap 'echo trap:; func; exit' SIGINT SIGTERM
    func() {
    echo func: $(pactl list | sed -E '/media\.name/p;d')
    }
    while true; do
    func
    sleep 1
    done

    关于bash - 了解bash信号处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60917722/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com