我正在从Kotlin启动bash脚本,但是一旦Kotlin应用程序退出,bash脚本就会停止运行。
val pr = ProcessBuilder("/home/vlad/liq", script, input).start()
其中脚本是液体肥皂脚本,输入是要传递到脚本中的参数
通常,它将运行以下内容:
./liq blah.liq http://somedomain.com:8090
liq
然后执行一个liquidsoap脚本,它是第一个参数,然后将第二个参数用作liquidsoap脚本的参数。
#!/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应用程序退出后如何保持脚本运行的任何想法吗?
答案 0 :(得分:1)
nohup
+ &
不会“生成新的控制台”。它只是创建一个忽略挂断信号的后台进程。有关更多信息,请参见Wikipedia article on nohup。
我不知道为什么杀死应用程序会杀死从它运行的程序,但是我可以建议一些尝试。
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
的更多信息,请参见On writing a Linux shell script to safely detach programs from a terminal和Difference between nohup, disown and &。
如果您还没有setsid
,或者它没有帮助,那么下一个选择是使用守护程序来运行命令(使其完全与将其设置为运行的过程无关) 。传统的方式是使用at
命令:
echo "/usr/bin/liquidsoap $1 -- $2" | at now
这要求atd
守护程序正在运行,并且您有权使用at
。有关at
的更多信息,请参见Run command 'at' 5 seconds from now。
从守护程序运行进程的现代方法是使用systemd-run
。有关使用systemd-run
代替at
的示例,请参见Shutdown, suspend require authentication when scheduled in at。