Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.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

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_Shell_Process Substitution - Fatal编程技术网

Linux bash陷阱与进程替换 更新

Linux bash陷阱与进程替换 更新,linux,bash,shell,process-substitution,Linux,Bash,Shell,Process Substitution,对于我发布的答案,我使用了一个更好的测试用例。我在这里添加了更新的测试用例,以防有人想进一步进行实验: #!/bin/bash mypts="$( tty )" # main traps trap "echo 'trapped SIGCHLD' >$mypts" SIGCHLD trap "echo 'trapped SIGHUP' >$mypts" SIGHUP trap "echo 'trapped SIGINT' >$mypts" SIGINT trap "ech

对于我发布的答案,我使用了一个更好的测试用例。我在这里添加了更新的测试用例,以防有人想进一步进行实验:

#!/bin/bash

mypts="$( tty )"

# main traps
trap "echo 'trapped SIGCHLD' >$mypts" SIGCHLD 
trap "echo 'trapped SIGHUP' >$mypts" SIGHUP 
trap "echo 'trapped SIGINT' >$mypts" SIGINT
trap "echo 'trapped SIGPIPE' >$mypts" SIGPIPE
trap "echo 'trapped SIGSEGV' >$mypts" SIGSEGV
trap "echo 'trapped SIGSYS' >$mypts" SIGSYS
trap "echo 'trapped SIGTERM' >$mypts" SIGTERM

function h4 {
    # function traps
    # these mask the main traps
    #trap "echo 'trapped h4 SIGCHLD'" SIGCHLD 
    #trap "echo 'trapped h4 SIGHUP'" SIGHUP 
    #trap "echo 'trapped h4 SIGINT'" SIGINT 
    #trap "echo 'trapped h4 SIGPIPE'" SIGPIPE 
    #trap "echo 'trapped h4 SIGSEGV'" SIGSEGV 
    #trap "echo 'trapped h4 SIGSYS'" SIGSYS 
    #trap "echo 'trapped h4 SIGTERM'" SIGTERM 

    {
        # compound statement traps
        # these mask the function traps
        #trap "echo 'trapped compound SIGCHLD'" SIGCHLD 
        #trap "echo 'trapped compound SIGHUP'" SIGHUP 
        #trap "echo 'trapped compound SIGINT'" SIGINT
        #trap "echo 'trapped compound SIGPIPE'" SIGPIPE 
        #trap "echo 'trapped compound SIGSEGV'" SIGSEGV 
        #trap "echo 'trapped compound SIGSYS'" SIGSYS 
        #trap "echo 'trapped compound SIGTERM'" SIGTERM 

        echo begin err 1>&2
        echo begin log
        # enable one of sleep/while/find
        #sleep 63
        #while : ; do sleep 0.1; done
        find ~ 2>/dev/null 1>/dev/null
        echo end err 1>&2
        echo end log
    } \
    2> >(
            trap "echo 'trapped 2 SIGCHLD' >$mypts" SIGCHLD
            trap "echo 'trapped 2 SIGHUP' >$mypts" SIGHUP
            trap "echo 'trapped 2 SIGINT' >$mypts" SIGINT
            trap "echo 'trapped 2 SIGPIPE' >$mypts" SIGPIPE
            trap "echo 'trapped 2 SIGSEGV' >$mypts" SIGSEGV
            trap "echo 'trapped 2 SIGSYS' >$mypts" SIGSYS
            trap "echo 'trapped 2 SIGTERM' >$mypts" SIGTERM
            echo begin 2 >$mypts
            awk '{ print "processed by 2: " $0 }' >$mypts &
            wait
            echo end 2 >$mypts
        ) \
    1> >(
            trap "echo 'trapped 1 SIGCHLD' >$mypts" SIGCHLD
            trap "echo 'trapped 1 SIGHUP' >$mypts" SIGHUP
            trap "echo 'trapped 1 SIGINT' >$mypts" SIGINT
            trap "echo 'trapped 1 SIGPIPE' >$mypts" SIGPIPE
            trap "echo 'trapped 1 SIGSEGV' >$mypts" SIGSEGV
            trap "echo 'trapped 1 SIGSYS' >$mypts" SIGSYS
            trap "echo 'trapped 1 SIGTERM' >$mypts" SIGTERM
            echo begin 1 >$mypts
            awk '{ print "processed by 1: " $0 }' >$mypts &
            wait
            echo end 1 >$mypts
        )
    echo end fnc
}

h4

echo finish
要获取ascii art进程树(在单独的终端中),请执行以下操作:

---
--- 我很难理解信号在bash中是如何传播的,以及哪个陷阱将处理它们

我这里有3个例子。每个示例都使用两种变体进行测试,即任一行未注释。示例由以下伪代码生成:

main_trap
func
    compound_statement(additional_traps) > process_redirection(additional_traps)
我试了几次两个品种的每一个例子。我得到的结果很少,我发布了我找到的结果

测试如下所示:

  • 将脚本放入文件中
  • 运行脚本文件
  • 脚本仍在运行时,按Ctrl+C
  • 注意:只需将这些脚本复制粘贴到现有bash shell中,就会产生与从文件执行时不同的结果。为了使这个问题的篇幅有所限制,我没有附上这些结果

    我的最终问题是:

    我使用这个布局(复合语句+进程重定向)来运行一些代码,并过滤和保存输出。现在出于某种原因,我决定更好地保护这个设置,以免在中断时终止,但我发现这真的很难做到。我很快就发现,仅仅在脚本开头调用trap是不够的

    是否有任何方法可以使用bash/trap保护我的脚本不受信号影响(并安装正确的关闭序列)

    信号倾向于先消除记录,所以我无法捕捉到主进程的垂死线

    (我在问题的末尾添加了更多的想法和分析。)

    这将是一个很长的问题,但我认为发布我已经完成的工作将有助于理解正在发生的事情:

    测试设置: 测试设置1(1类):

    结果:

    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    finish
    trapped 2
    
    begin
    ^Ctrapped 2
    end 2
    finish
    
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped inner
    trapped
    trapped 1
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped inner
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    trapped 2
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    trapped 1
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped
    trapped 1
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    trapped 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    测试设置2(2猫):

    结果:

    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    finish
    trapped 2
    
    begin
    ^Ctrapped 2
    end 2
    finish
    
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped inner
    trapped
    trapped 1
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped inner
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    trapped 2
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    trapped 1
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped
    trapped 1
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    trapped 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    测试设置3(2只猫,无睡眠子壳):

    结果:

    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    finish
    trapped 2
    
    begin
    ^Ctrapped 2
    end 2
    finish
    
    begin
    ^Ctrapped 2
    Segmentation fault
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped inner
    trapped
    trapped 1
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped inner
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped inner
    trapped 1
    trapped
    end
    
    # variation 1:
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    end 2
    finish
    end
    trapped 1
    trapped
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    trapped 2
    trapped 1
    trapped
    end
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    trapped 1
    trapped
    
    begin
    ^Cend 2
    finish
    trapped 2
    end
    trapped
    trapped 1
    
    begin
    ^Cend 2
    finish
    end
    trapped 2
    
    # variation 2:
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Cend 2
    trapped 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped
    end
    trapped 1
    
    begin
    ^Ctrapped 2
    end 2
    finish
    trapped 1
    trapped
    end
    
    我的分析是: 我添加所有3个测试用例的主要原因是,有时我会得到一个
    SEGFAULT
    。我把它扔掉了,但不知道它是从哪里来的。这似乎在某种程度上取决于主陷阱中的回声是否重定向到
    /dev/stderr
    (变体1)或不重定向(变体2)

    就在
    Ctrl+C
    之后,通常先激活
    “陷阱2”
    ,很少激活
    “结束2”
    。这表明(与我最初的想法相反),在处理信号时不涉及过程层次结构。正在运行的进程(复合语句,2个进程替换,在h和h2子shell中,
    sleep
    进程,
    cat
    进程)是并行运行的,无论哪个进程在发送信号时正在运行,都将对其进行处理。出于某种原因,这主要是stderr重定向的进程替换。我假设
    cat
    是主接收器,它没有安装信号处理程序,所以它就死了(这就是为什么我尝试添加2个
    cat
    s,以便第二个可以保持子shell运行)

    这就是问题所在,我没有真正的线索知道会发生什么。(我甚至不知道,如果我能做到这一点……)

    我认为,信号将从
    cat
    传播到其包含的进程,即安装了信号处理程序的进程替换bashshell,并打印
    “陷阱2”

    现在,我想,故事会在这里结束,一枚戒指被伊西尔多摧毁,佛罗多呆在家里。。。但是没有。不知怎的,它冒出了泡泡,并且成功地杀死了
    睡眠
    。即使有2个
    cat
    s,因此如果其中一个被破坏,子shell仍保持活动状态。我发现很有可能是一个
    SIGPIPE
    杀死了睡眠,因为在没有捕获它的情况下,我看到了一种与我在这里发布的行为不同的行为。但有趣的是,我似乎需要在每个位置设置
    陷阱
    SIGPIPE
    ,而不仅仅是在睡眠子shell中,或者再一次,它显示了不同的行为

    我猜,
    SIGPIPE
    信号到达
    sleep
    ,杀死它,因此复合语句中只剩下一个
    echo
    ,它执行,子shell完成。stdout重定向的进程替换也被终止,可能是由另一个
    SIGPIPE
    终止的复合语句/函数shell终止的

    更有趣的是,有时根本没有显示
    “trapped 1”

    奇怪的是,我没有看到50%的被困2和50%的被困1

    我能做什么,我想用这个做什么? 请记住,我的目标是有序地关闭系统/服务/脚本

    1) 首先,如我所见,如果这里由
    sleep
    /
    cat
    表示的“业务流程”没有自己的信号处理,那么再多的
    陷阱也无法避免它们被杀死

    2) 信号处理程序不是继承的,每个子shell都必须有自己的陷阱系统

    3) 没有什么比进程组更能以公共方式处理信号了,不管信号发生在哪个进程上,它都能完成自己的任务,在那里被杀死的进程的结果可能会在进程树中进一步传播

    但我不清楚,如果一个进程不能处理一个信号,它会把它扔到它的外壳中吗?还是另一个信号,传递的是什么?肯定有什么东西通过了,否则信号处理器就不会被触发

    在我的理想世界中,
    trap
    将保护安装在外壳内的任何东西不被接收到信号,因此
    睡眠
    -s、
    -s将被指定的清理功能关闭:杀死
    
    
    # variation 1
    # trap "echo 'trapped' >/dev/stderr" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    trapped 1
    trapped
    ^Ctrapped 2
    ^CSegmentation fault
    
    # variation 2
    # trap "echo 'trapped'" SIGTERM SIGINT SIGHUP SIGPIPE
    begin
    ^Ctrapped 2
    trapped 1
    trapped
    ^Ctrapped 2
    ^CSegmentation fault
    
    ^Ctrapped 2
    trapped 1
    trapped
    ^Ctrapped 2
    Segmentation fault
    
    2> >( cat & )
    
    {
        cmd
    } \
    2> >(logger) \
    1> >(logger)
    
    f {
        {
            cmd
        } \
        2> >(logger) \
        1> >(logger)
    }
    
    trap ...
    
    set -m
    f &
    wait