如何从 Java 代码(JSP/Servlet)中停止另一个 tomcat

Posted

技术标签:

【中文标题】如何从 Java 代码(JSP/Servlet)中停止另一个 tomcat【英文标题】:How to stop another tomcat from Java code (JSP/Servlet) 【发布时间】:2020-11-24 19:19:03 【问题描述】:

我有两个tomcat安装如下:

    Tomcat-A 路径:C:\TomcatA,端口:连接器端口 =“8080” redirectPort="8443" 关闭端口为 -1 Tomcat-B 路径:C:\TomcatB,端口:连接器端口 =“8090” redirectPort="8444" 关闭端口为 8015

我有一个在 Tomcat-A 上运行的 JSP/Servlet 应用程序。我的要求是关闭 Tomcat-B 并删除/取消部署托管在 Tomcat-B 上的应用程序。下面是我的 Java 代码。

private void StopTomcat() throws Exception 
    if(logger.isDebugEnabled()) logger.debug("StopTomcat");

    try 

        if (logger.isTraceEnabled())logger.trace("Shutting down tomcat: ");

        String Directory = "C:\TomcatB\bin\";

        Process process = Runtime.getRuntime().exec(Directory + "shutdown.bat");

        if (logger.isTraceEnabled())logger.trace("Executed shutdown.bat at " + Directory );
        
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));

        if (logger.isTraceEnabled())logger.trace("Printing shutdown process logs" );
        String s = null;
        while ((s = stdInput.readLine()) != null) 
            if (logger.isTraceEnabled())
                logger.trace(s);
        
        String Error = "";
        while ((s = stdError.readLine()) != null) 
            Error = Error + s;
        

        if (!Error.equals("")) 
            logger.error(Error);
            throw new Exception("Tomcat Shutdown Failed with error: " + Error);
        
        
     catch (Exception e) 
        e.printStackTrace();
        logger.error( Arrays.toString( e.getStackTrace() ));
        throw new Exception(e.getMessage());
    

在我得到的日志中:

2020-08-04 21:11:00 TRACE MigrateApp:55 - Executed shutdown.bat at C:\TomcatB\bin\
2020-08-04 21:11:00 TRACE MigrateApp:60 - Printing shutdown process logs
2020-08-04 21:11:00 TRACE MigrateApp:64 - Using CATALINA_BASE:   "TomcatA"
2020-08-04 21:11:00 TRACE MigrateApp:64 - Using CATALINA_HOME:   "TomcatA"
2020-08-04 21:11:00 TRACE MigrateApp:64 - Using CATALINA_TMPDIR: "TomcatA\temp"
2020-08-04 21:11:00 TRACE MigrateApp:64 - Using JRE_HOME:        "C:\Program Files\Java\jre1.8.0_251"
2020-08-04 21:11:00 TRACE MigrateApp:64 - Using CLASSPATH:       "TomcatA\bin\bootstrap.jar;TomcatA\bin\tomcat-juli.jar"
2020-08-04 21:11:00 ERROR MigrateApp:72 - 04-Aug-2020 21:11:00.668 SEVERE [main] org.apache.catalina.startup.Catalina.stopServer No shutdown port configured. Shut down server through OS signal. Server not shut down.
2020-08-04 21:11:00 ERROR MigrateApp:78 - [sailpoint.support.applicationdeployer.util.MigrateApp.StopTomcat(MigrateApp.java:73), sailpoint.support.applicationdeployer.util.MigrateApp.run(MigrateApp.java:36)]
2020-08-04 21:11:00 ERROR MigrateApp:79 - Tomcat Shutdown Failed with error: 04-Aug-2020 21:11:00.668 SEVERE [main] org.apache.catalina.startup.Catalina.stopServer No shutdown port configured. Shut down server through OS signal. Server not shut down.
2020-08-04 21:11:00 ERROR MigrateApp:39 - Tomcat Shutdown Failed with error: 04-Aug-2020 21:11:00.668 SEVERE [main] org.apache.catalina.startup.Catalina.stopServer No shutdown port configured. Shut down server through OS signal. Server not shut down.

我无法理解为什么我的代码试图关闭 Tomcat-A。任何人都可以帮助我吗?

【问题讨论】:

【参考方案1】:

我可以通过如下修改 exec 参数来实现。它现在可以正常工作了。

String Directory = "C:\TomcatB\bin\";
File workingDirecotry = new File(Directory);
Process process = Runtime.getRuntime().exec(Directory + "shutdown.bat", null, workingDirecotry);

【讨论】:

【参考方案2】:

如果您尚未编辑 Tomcat B shutdown.bat 默认脚本,您将看到 C:\TomcatB\bin\shutdown.bat 确定 CATALINA_HOME 并执行:

%CATALINA_HOME%\bin\catalina.bat

看起来您的 TomcatA 虚拟机正在将自己的 CATALINA_HOME 传递给 Tomcat B shutdown.bat,这会覆盖 C:\TomcatB\bin 使用的默认值。您可以创建一个不假定 CATALINA_HOME 环境变量的新脚本 shutdown2.bat,或者切换到 ProcessBuilder 并在 ProcessBuilder 启动命令中设置 CATALINA_HOME,如下所示:

File exe = new File(Directory, "shutdown.bat");
String [] cmd = new String[]  exe.getAbsolutePath() ;
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.environment().put("CATALINA_HOME", exe.getParentFile().getParentFile().getAbsolutePath());
Process process = pb.start();

如果进程锁定,您可能需要在后台线程中使用输出/错误流或通过在 start() 之前调用将它们重定向到文件:

pb.redirectOutput(outfile);
pb.redirectError(errfile);

【讨论】:

以上是关于如何从 Java 代码(JSP/Servlet)中停止另一个 tomcat的主要内容,如果未能解决你的问题,请参考以下文章

JSP与Servlet的介绍说明

JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系

JSP基础知识

jsp/servlet学习笔记(核心编程)servlet部分

jsp,servlet的基本原理和作用

Java Web 技术(JSP 和 servlet)中的 AJAX 自动完成文本框