0

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

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

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

但是按 Ctrl+C 显然只会杀死tail进程,而不是主体。我可以两者兼得吗?也许使用屏幕?

4

3 回答 3

1

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

screen -S SOMENAME script.sh

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

screen -r SOMENAME

Ctrl+C应该继续按预期工作

于 2013-11-14T01:36:32.573 回答
1

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

事实 2Ctrl-的效果C取决于您的终端设置。通常,它会发送一个 SIGINT,但你可以通过stty -a在你的 shell 中运行并寻找“ 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它的名字是从哪里来的了吗?)

于 2013-11-14T04:50:37.197 回答
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
于 2013-11-14T17:34:53.100 回答