首页 > 解决方案 > 退出 Java / Kotlin 应用程序时停止 bash 脚本死亡

问题描述

我正在从 Kotlin 启动一个 bash 脚本,但是一旦 Kotlin 应用程序退出,bash 脚本就会停止运行。

val pr = ProcessBuilder("/home/vlad/liq", script, input).start()

其中 script 是 Liquidsoap 脚本,而 input 是传递给脚本的参数

通常,它会运行如下内容:

./liq blah.liq http://somedomain.com:8090

liq然后执行作为第一个参数的液体肥皂脚本,然后将第二个参数用作液体肥皂脚本的参数。

#!/bin/bash

nohup /usr/bin/liquidsoap $1 -- $2 > /dev/null 2>&1 &

# this causes syntax error
# nohup (/usr/bin/liquidsoap $1 -- $2 > /dev/null 2>&1 &)

这个 Kotlin 应用程序通过运行java -jar dashboard.jar,当应用程序运行时,liquidsoap 脚本正在运行,只要我使用 Ctrl + C 退出 Kotlin 应用程序,liquidsoap 脚本也会停止。

我的印象是nohup+&会产生一个新的控制台,从而即使在 Kotlin 应用程序退出后也能保持脚本运行,但事实并非如此。

即使在我的 Kotlin 应用程序退出后如何保持脚本运行的任何想法?

标签: javalinuxbashkotlin

解决方案


nohup+&不会“产生新的控制台”。它只是创建一个忽略挂断信号的后台进程。有关更多信息,请参阅关于 nohup 的 Wikipedia 文章。

我不知道为什么杀死应用程序会杀死从中运行的程序,但我可以建议一些尝试。

Nahuel Fouilleul 建议的双叉是个好主意。正确语法的一个例子是:

( nohup /usr/bin/liquidsoap $1 -- $2 </dev/null >/dev/null 2>&1 & )
sleep 1 # Wait to ensure that 'nohup' takes effect

</dev/null不是必需的,nohup但为了保持一致性,我添加了它。这sleep 1是为了避免前台和后台进程之间可能出现的竞争条件。

如果这不起作用,则该setsid命令(如果您拥有它)可以通过将子进程放入单独的进程组和会话中来进一步将子进程与其父进程隔离。示例用法是:

( setsid /usr/bin/liquidsoap $1 -- $2 </dev/null >/dev/null 2>&1 & )
sleep 1 # Wait to ensure that 'setsid' takes effect

有关. _ _ _ _setsid

如果您没有setsid,或者它没有帮助,下一个选项是使用守护程序来运行命令(使其与设置它运行的进程完全无关)。执行此操作的传统方法是使用以下at命令:

echo "/usr/bin/liquidsoap $1 -- $2" | at now

这要求atd守护程序正在运行并且您有权使用at. 有关. _ _at

从守护进程运行进程的现代方法是使用systemd-run. 有关使用systemd-run不是at.


推荐阅读