我想编写一个 bash 脚本,如果用户断开连接,它将继续运行,但如果用户按 Ctrl+C 则可以中止。
我可以像这样解决它的第一部分:
#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out
但是按 Ctrl+C 显然只会杀死tail
进程,而不是主体。我可以两者兼得吗?也许使用屏幕?
我想编写一个 bash 脚本,如果用户断开连接,它将继续运行,但如果用户按 Ctrl+C 则可以中止。
我可以像这样解决它的第一部分:
#!/bin/bash
cmd='
#commands here, avoiding single quotes...
'
nohup bash -c "$cmd" &
tail -f nohup.out
但是按 Ctrl+C 显然只会杀死tail
进程,而不是主体。我可以两者兼得吗?也许使用屏幕?
这可能是使用屏幕最简单的形式:
screen -S SOMENAME script.sh
然后,如果您断开连接,重新连接时只需运行:
screen -r SOMENAME
Ctrl+C
应该继续按预期工作
事实 1:当终端(例如 xterm)关闭时,shell 应该向其中运行的任何进程发送 SIGHUP(“挂断”)。这可以追溯到模拟调制解调器的时代,如果你在线时妈妈碰巧拿起电话,程序需要自行清理。信号可能会被捕获,因此可以使用特殊功能进行清理(关闭文件、删除临时垃圾等)。即使我们使用套接字和 SSH 隧道而不是模拟调制解调器,“失去连接”的概念仍然存在。(概念不会改变;所有改变的是我们用来实现它们的技术。)
事实 2:Ctrl-的效果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
它的名字是从哪里来的了吗?)
我想编写一个 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