如何防止通过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改变了。