首页 > 解决方案 > 启动大量后台作业,但将它们的日志分开

问题描述

我对unix中的shell命令几乎没有经验。到目前为止,我已经检查了 stackOverflow 并知道如何按顺序运行简单的 shell 脚本

  1. 使用回声
echo $(sh dosomthing1.sh)
echo $(sh dosomthing2.sh)
  1. 直接使用 sh xxx 并等待
sh dosomthing1.sh
wait 
sh dosomthing2.sh
  1. 使用 &&
sh dosomthing1.sh && sh dosomthing2.sh

但是这些方法似乎无助于解决我的问题......

这是我的问题:

我有一个基本的 shell 脚本来进行 maven 编译,然后使用“nohup xxx &”在后台启动一个 java 应用程序。脚本如下所示:

#get the input env parameter
env=$1

#goto application root directory
cd /applicationDir

#to compile
mvn install -Dmaven.test.skip=true

#to start with parameter env
nohup java -jar -Dspring.profiles.active=$env myApplication.jar &

#to tail the log
tail -20f myApplication.log

我有太多不同的应用程序具有相同的启动脚本,很难一个一个地启动它们。我需要用一个命令启动它们。

所有的 shell 脚本都应该按顺序一一处理。如果有任何异常,请跳过并运行下一个。

当我尝试编写这样的脚本时:

sh start1.sh
wait
echo "application 1 was start up"

sh start2.sh
wait
echo "application 2 was start up"

...

sh startxxx.sh
wait
echo "application xxx was start up"

虽然所有子 shell 脚本都会按照我的预期按顺序处理,并且输出信息看起来 shell 运行良好,但事实是只会启动最后一个应用程序,之前的所有命令“nohup xxxx &”将是关闭。

我也试过这样写:

sh start1.sh &

sh start2.sh &

...

sh startxxx.sh &

虽然结果是我想要的,所有的应用程序都会很好地启动,但是在处理脚本的过程中,由于脚本的并行运行,控制台输出是不可读的。它得到了一个很好的结果,但不是一个优雅的方式。

我不知道如何解决这个问题......

请帮我解决这个问题,非常感谢!

标签: linuxbashshell

解决方案


当你有一个带有命令的脚本时,你可以做chmod +x start.sh. 现在脚本可以用./start.sh. 您将避免额外的sh过程,并且ls -l可以查看哪些脚本是可执行的。
在您的脚本中,您有tail -f. 这对于后台进程来说将是非常混乱的。在后台启动脚本并从控制台查看日志记录。我确实希望每个脚本都使用不同的myApplication.jarmyApplication.log.
当日志文件中的日志记录在标准输出(您的命令行窗口)中重复时,您可以丢弃该日志记录。

./start1.sh > /dev/null 2>&1 &
./start2.sh > /dev/null 2>&1 &
./startxxx.sh > /dev/null 2>&1 &

当您在脚本终止之前注销时,这些进程将被终止。这可以通过以下方式避免nohup

nohup ./start1.sh > /dev/null 2>&1 &
nohup ./start2.sh > /dev/null 2>&1 &
nohup ./startxxx.sh > /dev/null 2>&1 &

编辑:
OPS 想要以固定顺序启动程序。
按顺序一个接一个地启动脚本,应该可以通过以正确的顺序调用它们(可能还有一个额外的sleep 1)。
当您需要等待程序 1 完成一些初始化内容时,您需要检查它。使用 1 个脚本调用所有脚本并添加一些控制语句,例如

nohup java something &
while ! grep -q "Started" myApplication.log; do 
   sleep 1
done

当java程序出错时,while将永远等待,所以用一些最大重试次数替换它

for ((retry=0l retry<100; retry++)); do
   grep -q "Started" myApplication.log && break
   sleep 1
done

推荐阅读