Bash脚本将在断开连接但不会在用户中断时继续存在

时间:2013-11-14 00:29:04

标签: bash gnu-screen nohup

我想编写一个bash脚本,如果用户断开连接将继续运行,但如果用户按下Ctrl + C,则可以中止。

我可以像这样解决它的第一部分:

#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out

但是按Ctrl + C显然只会杀死tail进程,而不是主体。我可以同时拥有吗?也许使用Screen?

3 个答案:

答案 0 :(得分:1)

这可能是使用屏幕的最简单形式:

screen -S SOMENAME script.sh

然后,如果断开连接,重新连接时只需运行:

screen -r SOMENAME

Ctrl+C应继续按预期工作

答案 1 :(得分:1)

事实1 :当终端(例如xterm)关闭时,shell应该向其中运行的任何进程发送SIGHUP(“挂断”)。这可以追溯到模拟调制解调器的日子,当一个程序需要自己清理,如果妈妈碰巧在你上网时拿起电话。信号可能被捕获,因此特殊功能可以进行清理(关闭文件,删除临时垃圾等)。即使我们使用套接字和SSH隧道而不是模拟调制解调器,“丢失连接”的概念仍然存在。 (概念不会改变;所有改变都是我们用来实现它们的技术。)

事实2 Ctrl - C 的效果取决于您的终端设置。通常情况下,它会发送一个SIGINT,但您可以在shell中运行stty -a并查找“ intr ”进行检查。

您可以使用bash的trap命令来利用这些事实。例如,尝试在窗口中运行它,然后按Ctrl-C并检查/tmp/trapped的内容。然后再次运行它,关闭窗口,再次检查/tmp/trapped

的内容
#!/bin/bash

trap "echo 'one' > /tmp/trapped" 1
trap "echo 'two' > /tmp/trapped" 2

echo "Waiting..."
sleep 300000

有关信号的信息,您应该能够man signal(FreeBSD或OSX)或man 7 signal(Linux)。

(奖励积分:看看我如何编号我的事实?你明白为什么吗?)

所以......对你的问题。要“生存”断开连接,您需要指定在脚本捕获SIGHUP时将运行的行为。

(奖金问题#2:现在您了解nohup取名的位​​置吗?)

答案 2 :(得分:1)

我想编写一个bash脚本,如果用户断开连接将继续运行,但如果用户按下Ctrl + C,则可以中止。

我认为这正是你提出的问题的答案,这个没有屏幕:

#!/bin/bash
cmd=`cat <<EOF
# commands here
EOF
`
nohup bash -c "$cmd" &

# store the process id of the nohup process in a variable
CHPID=$!        

# whenever ctrl-c is pressed, kill the nohup process before exiting
trap "kill -9 $CHPID" INT

tail -f nohup.out

但请注意,nohup不可靠。当调用用户注销时,很可能nohup也会立即退出。在这种情况下, disown 效果更好。

bash -c "$cmd" &
CHPID=$!
disown