Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.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
如何防止通过su-c调用的bash脚本在SIGINT之后挂起_Bash_Shell_Su_Bash Trap - Fatal编程技术网

如何防止通过su-c调用的bash脚本在SIGINT之后挂起

如何防止通过su-c调用的bash脚本在SIGINT之后挂起,bash,shell,su,bash-trap,Bash,Shell,Su,Bash Trap,我有两个脚本。这些都是简化的。root script.sh调用userscript.sh: root-script.sh: #!/bin/bash su - user1 -c "/user1path/user-script.sh" #!/bin/bash trap 'echo please use x for exit' 2 while x=0; do read -p "enter x for exit:" answer if [[ $answer = 'x' ]]

我有两个脚本。这些都是简化的。
root script.sh
调用
userscript.sh

root-script.sh:

 #!/bin/bash 
 su - user1 -c "/user1path/user-script.sh"
 #!/bin/bash
 trap 'echo please use x for exit' 2
 while x=0; do
    read -p "enter x for exit:" answer
    if [[ $answer = 'x' ]]; then
            echo "exit now"
            exit 0
    fi
 done
user-script.sh:

 #!/bin/bash 
 su - user1 -c "/user1path/user-script.sh"
 #!/bin/bash
 trap 'echo please use x for exit' 2
 while x=0; do
    read -p "enter x for exit:" answer
    if [[ $answer = 'x' ]]; then
            echo "exit now"
            exit 0
    fi
 done
如果我调用user-script.sh,它会正常工作:

 enter x for exit:
 enter x for exit: ^C_please use x for exit
^C_please use x for exit
x
exit now
如果我调用
root script.sh
作为
root
并输入Ctrl-C,我会得到

 enter x for exit: ^C
Session terminated, killing shell... ...killed.
然后返回根提示符,但该提示符被阻止。 使用ps,我看不到根脚本,只有用户脚本。 如果我杀死用户脚本,根提示符将再次可用

如何防止根脚本用户脚本构造在SIGINT之后挂起? 对我来说意味着什么

  • 正在退出
    root script.sh
    user script.sh
  • 根脚本用户脚本的构造应与
    user script.sh

    • bash版本:3.2.51(1)-发行版(x86_64-suse-linux-gnu)
    • 操作系统版本:sles11 3.0.93-0.8-default
  • 我刚刚测试过:

    su -c 'trap /bin/true 2; while true; do sleep 1; done' user
    
    诗句

    su -c 'while true; do sleep 1; done' user
    
    发现前者不能通过SIGINT终止,但后者可以。我的猜测是,也许su-c打开用户的shell来运行由-c传递的命令,这将捕获SIGINT并终止-但是您的脚本只在子shell中捕获SIGINT-父shell的SIGINT处理程序可能会传递SIGTERM

    希望这对你有用

    编辑:

    确认命令与用户的shell一起运行

    也许你会发现

    su -c 'exec my_script.sh' user
    
    这是一个更优雅的解决方案。我认为它会起作用,但还没有测试过。exec将用脚本的进程替换当前的shell进程,因此我认为它应该可以工作

    编辑2:

    回顾你的问题,我认为你只需要根脚本中的陷阱。或者可能:

    exec 'su -c "exec script.sh" user'
    

    如果您想完全继承脚本的陷阱行为。

    本文解释了为什么不将SIGINT传递到
    su-c
    中,并给出了一个解决方案:

    在您的例子中:
    su-user1--session命令“/user1path/user script.sh”

    由于
    --session command
    是一个不推荐的选项(请参阅),如果您觉得不安全,也可以在您的情况下使用
    -s
    选项:


    su-user1-s/user1path/user script.sh

    我想象
    su
    设置了自己的
    SIGINT
    处理程序,您无法轻松覆盖它。为什么您允许用户以其他用户的身份运行交互式shell脚本?你或许应该重新思考一下逻辑。可能
    读取输入;su-user1 otherscript“$input”
    这两个脚本都是纯粹的简化。所以所有其他的东西都被去掉了。这种逻辑几乎无法修改。
    su-c'exec my_script.sh'用户
    终止了这两个脚本。我发现在linux上有一个选项
    su-C(大写)
    ,使用这个选项脚本将不会终止并按预期工作。但是脚本也必须在solaris上运行,并且没有这样的选项。根脚本中的陷阱没有帮助。在杀戮消息之后我收到了根脚本陷阱文本。我不知道该建议什么。我现在已经测试了两个脚本,一个.sh包含#/bin/bash\n陷阱“echo hello”2\n为true;做睡眠1;完成。和2.sh包含#/bin/bash\n su-c'exec./one.sh'用户。当我执行two.sh并发送一个SIGINT时,它由one.sh为我处理。奇怪:-/.
    su-c'虽然是真的;做睡眠1;“完成”user
    似乎不起作用,而:Expression语法。经过长时间搜索后,我发现--session命令不在Ubuntu 16.04的su上,而是在runuser(只能由root运行)中。该命令在raspberryOS(linux/arm/v7)上起作用,但在Ubuntu:20.04(linux/arm/v7)()上构建的docker容器中不起作用。PID改变了。