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

ant*_*nio 15 command-line signals job-control shell-script background-process

我想从脚本运行和配置一个类似于守护进程的进程。
我的 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 &
Run Code Online (Sandbox Code Playgroud)

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

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

  • 点击Enter脚本结束该过程保留在后台。

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

另一种方法 在后台运行整个脚本。'Would be',但read如果脚本作为startserv.sh &.

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

Joh*_*ith 19

点击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 &
Run Code Online (Sandbox Code Playgroud)

disown替代

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

disown -h $cmd &
Run Code Online (Sandbox Code Playgroud)

“很好地”杀死后台进程

现在,当涉及到杀死你的过程中,你可以完全做一个“ Ctrl+ C”使用kill。只是不要发送一个残酷的SIGKILL。相反,您可以使用:

$ kill -2 [PID]
$ kill -15 [PID]
Run Code Online (Sandbox Code Playgroud)

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

...
nohup $cmd &
echo $!
Run Code Online (Sandbox Code Playgroud)

...或者更好的是,让脚本等待 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
Run Code Online (Sandbox Code Playgroud)

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

trap "kill -15 $bg_pid" 2 15
Run Code Online (Sandbox Code Playgroud)

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