代码之家  ›  专栏  ›  技术社区  ›  milahu

SIGTSTP(Ctrl-Z)只停止子shell,但父shell保持运行-交互式bash-shell

  •  0
  • milahu  · 技术社区  · 1 年前

    在交互式bash shell中,我想调用一个函数,
    它启动一个子shell,以运行一些bash代码

    f() { echo a; ( sleep 5; ); echo z $?; }; f
    

    我需要潜艇来接 exit 1 根据bash代码,
    所以我的交互式bash shell一直在运行。
    另请参阅 Is there a TRY CATCH command in Bash

    例如,子shell中的代码是一个长时间运行的进程 sleep 5

    问题:当我调用函数并发送SIGTSTP(Ctrl-Z)时,
    然后只有子shell停止,主函数继续运行

    预期:SIGTSTP(Ctrl-Z)应该停止主函数和子shell,
    和SIGCONT(fg)应继续同时运行

    解决方法: build bash with --disable-job-control ,
    因为 set +m 不起作用,并且 stty susp undef 限制性太强

    $ f() { echo a; ( sleep 5; ); echo z $?; }; f
    a
    ^Z
    [1]+  Stopped                 ( sleep 5 )
    z 148
    
    $ fg
    ( sleep 5 )
    
    $
    

    返回代码148表示128+20,并且20==SIGTSTP
    另请参阅 Exit status ($?) of 148 upon Ctrl+Z

    具有 wait -f %1 在主要功能中,
    主函数挂起,我不得不中断(Ctrl-C)

    %1 在这里工作,因为只有一份工作

    $ f() { echo a; ( sleep 5; ); wait -f %1; echo z $?; }; f
    a
    ^Z
    [1]+  Stopped                 ( sleep 5 )
    bash: warning: wait_for_job: job 1 is stopped
    ^Z^Z^Z^Z^Z^Z^C
    
    $
    

    具有 trap "" SIGTSTP 在子shell中,SIGTSTP(Ctrl-Z)被忽略

    $ f(){ echo a; ( trap "" SIGTSTP; sleep 5; ); echo z $?; }; f
    a
    ^Z^Z^Z^Z^Z^Z^Zz 0
    
    $ 
    

    具有 trap handle_tstp SIGTSTP 在潜艇外壳中,
    交互式shell挂在SIGTSTP(Ctrl-Z)上

    $ f(){ echo a; ( s() { echo s; }; trap s SIGTSTP; sleep 5; ); echo z $?; }; f
    a
    ^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^Z^C^C^C^C^C^C^C^C^C^C^C^C^C
    

    陷阱句柄_tstp SIGTSTP 在主要功能中没有效果

    f(){ s() { echo s; }; trap s SIGTSTP; echo a; ( sleep 5; ); echo z $?; }; f 
    

    kill -SIGTSTP $$ 在主要功能中没有效果,
    所以主功能无法自行停止

    f(){ echo a; ( sleep 5; ); kill -SIGTSTP $$; echo z $?; }; f
    

    $$ $BASHPID ,父shell与子shell

    $ f(){ echo par $$ $BASHPID; ( echo sub $$ $BASHPID; ) }; f
    par 613627 613627
    sub 613627 613652
    

    我尝试了更多的技巧。。。但是SIGTSTP总是只停止一部分并且另一部分保持在后台运行。我还试图手动捕获SIGTSTP kill -SIGTSTP $subshell_pid 但是陷阱无法捕获SIGTSTP

    这样,SIGTSTP将被忽略

    r() { echo $$.b; while read -r L; do echo "$$.b $L"; done <$1; echo $$.d; }; f() { echo $$.a; r <( for ((i=0;i<5;i++)); do echo $BASHPID.c.$i; sleep 1; done; ); echo $$.z $?; }; f

    有了这些,SIGTSTP只停止前台进程

    r() { echo $$.b; cat $1 | while read -r L; do echo "$$.b $L"; done; echo $$.d; }; f() { echo $$.a; r <( for ((i=0;i<5;i++)); do echo $BASHPID.c.$i; sleep 1; done; ); echo $$.z $?; }; f

    r() { echo $$.b; cat $1; echo $$.d; }; f() { echo $$.a; r <( for ((i=0;i<5;i++)); do echo $BASHPID.c.$i; sleep 1; done; ); echo $$.z $?; }; f

    r() { echo $$.b; t() { echo trap; }; trap t SIGTSTP; cat $1 | while read -r L; do echo "$$.b $L"; done; echo $$.d; }; f() { echo $$.a; r <( for ((i=0;i<5;i++)); do echo $BASHPID.c.$i; sleep 1; done; ); echo $$.z $?; }; f

    另请参阅: Why does a subshell of an interactive shell run as an interactive shell?

    子shell继承父级的所有特性

    0 回复  |  直到 1 年前