从脚本启动后台进程并在脚本结束时对其进行管理

从脚本启动后台进程并在脚本结束时对其进行管理

我想运行和配置一个类似于脚本中守护进程的进程。
我的 shell 是在 Cygwin 下模拟 zsh 的,守护进程是SFK,一个基本的FTP服务器。

对于这里重要的事情,脚本startserv.sh可以起草如下:

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
$cmd &

运行脚本后startserv.sh,它停止(结束?),没有显示任何提示,然后:

  • CTRL+C结束脚本和后台作业进程;

  • 点击Enter脚本结束进程仍保留在后台。

无论如何,我只能通过ps而不是看到它jobs,所以,当我想关闭进程时,我必须发送一个残酷的kill -9信号,这是我想避免的有利于 CTRL+ 的事情C

替代 将会在后台运行整个脚本。 “将是”,但read如果脚本作为 运行,则该命令无法获取用户输入startserv.sh &

请注意,我需要一个临时服务器,而不是真正的服务器守护进程:也就是说,我希望服务器进程在后台运行,在脚本结束后执行简单的交互式 shell 任务(使用虚拟机来宾),但我不需要该进程在 shell 中存活;因此nohup似乎不合适。

答案1

点击Enter脚本结束进程仍保留在后台。

几乎!实际上,当您按 时脚本已经退出Enter。但是,这就是您可以恢复提示符的方法(因为您的 shell 会$PS1再次打印它)。

之所以点击Ctrl+C会终止它们两个,是因为它们两个是链接的。当您执行脚本时,您的 shell 会启动一个子 shell 来运行它。当您终止此子 shell 时,您的后台进程可能会因信号而终止SIGHUP

将脚本、后台进程和子shell分开

使用nohup,您也许能够摆脱这个小小的不便。

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

另一种disown选择

如果您可以从 切换/bin/sh/bin/bash,您也可以尝试一下disown。要了解更多信息,只需输入help disown一个bash实例即可。

disown -h $cmd &

“很好地”终止后台进程

现在,当涉及到终止进程时,您可以使用 完美地执行“ Ctrl+ Ckill。只是不要发送残酷的信息SIGKILL。相反,您可以使用:

$ kill -2 [PID]
$ kill -15 [PID]

这将向您的进程发送一个很好的SIGINT(2) 或(15)。SIGTERM您可能还想在启动进程后打印 PID 值:

...
nohup $cmd &
echo $!

...或者更好的是,让脚本等待 a SIGINT,然后将其发送回后台进程(这将使您的脚本保持在前台):

#!/bin/sh
read -s -p "Enter Password: " pw
user=testuser
share=/fshare
cmd="sfk ftpserv -user=$user -pw=$pw -usedir $share=$share"
nohup $cmd &

# Storing the background process' PID.
bg_pid=$!

# Trapping SIGINTs so we can send them back to $bg_pid.
trap "kill -2 $bg_pid" 2

# In the meantime, wait for $bg_pid to end.
wait $bg_pid

如果 aSIGINT不够,只需使用 aSIGTERM代替 (15) :

trap "kill -15 $bg_pid" 2 15

这样,当您的脚本收到后台进程的SIGINT( Ctrl+ C, kill -2) 或SIGTERMwhile waiting 时,它只会将信号中继给它。如果这些信号确实杀死了sfk实例,那么wait调用将返回,因此也会终止您的脚本:)

相关内容