You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Java代码自动重启当前承载应用的Tomcat?

解决Tomcat进程内执行重启代码导致无法重启的问题

你的问题核心很清晰:当你在Tomcat自身的Java进程里执行killall java时,这个命令会直接终止当前运行这段代码的Tomcat进程,导致后续的启动命令根本没机会执行——毕竟你的重启逻辑是Tomcat进程的一部分,进程都被干掉了,代码自然跟着停了。

下面给你几个可行的解决方案,按推荐程度排序:

方案1:将重启逻辑剥离到独立脚本(最可靠)

把重启的逻辑放到一个独立的shell脚本里,让Tomcat进程只负责触发这个脚本,脚本在后台完成"杀Tomcat+启动Tomcat"的操作,这样Tomcat自身的终止不会影响脚本的执行。

具体步骤:

  1. 创建restart_tomcat.sh脚本,内容如下:
#!/bin/bash
# 精准杀死Tomcat进程(避免误杀其他Java进程)
# 通过进程名筛选Tomcat PID
TOMCAT_PID=$(ps aux | grep tomcat6 | grep -v grep | awk '{print $2}')
if [ ! -z "$TOMCAT_PID" ]; then
    kill $TOMCAT_PID
    # 等待进程彻底终止
    sleep 5
fi
# 启动Tomcat
cd /root/cluster/tomcat6/bin
./startup.sh
  1. 给脚本添加执行权限:chmod +x restart_tomcat.sh
  2. 修改Java代码,调用这个脚本并让它在后台运行:
try {
    PreparedStatement.setQueryTimeout(10);
    rs = PreparedStatement.executeQuery();
} catch (SQLException ex) {
    System.out.println("IN CATCH BLOCK FOR THE REFRESH INVOICE");
    // 用nohup让脚本脱离当前进程后台运行,不受Tomcat终止影响
    String restartCommand = "nohup /path/to/restart_tomcat.sh > /dev/null 2>&1 &";
    Process process = Runtime.getRuntime().exec(restartCommand);
    System.out.println("Tomcat restart triggered");
}

方案2:精准杀死Tomcat进程,而非所有Java进程

如果你不想用独立脚本,至少要避免killall java——这会杀掉所有Java进程(包括当前运行重启代码的进程)。可以通过Tomcat的PID文件或监听端口精准定位进程:

示例代码:

try {
    PreparedStatement.setQueryTimeout(10);
    rs = PreparedStatement.executeQuery();
} catch (SQLException ex) {
    System.out.println("IN CATCH BLOCK FOR THE REFRESH INVOICE");
    
    // 读取Tomcat生成的PID文件(启动时会在bin目录生成catalina.pid)
    String getPidCommand = "cat /root/cluster/tomcat6/bin/catalina.pid";
    Process pidProcess = Runtime.getRuntime().exec(getPidCommand);
    BufferedReader reader = new BufferedReader(new InputStreamReader(pidProcess.getInputStream()));
    String tomcatPid = reader.readLine();
    reader.close();
    
    if (tomcatPid != null && !tomcatPid.isEmpty()) {
        // 杀死Tomcat进程
        String killCommand = "kill " + tomcatPid;
        Runtime.getRuntime().exec(killCommand);
        // 等待进程完全终止
        Thread.sleep(5000);
        
        // 后台启动Tomcat,避免当前进程终止影响启动命令
        String startCommand = "nohup /root/cluster/tomcat6/bin/startup.sh > /dev/null 2>&1 &";
        Runtime.getRuntime().exec(startCommand);
    }
} catch (Exception e) {
    e.printStackTrace();
}

注意:这种方式仍有风险,如果Tomcat进程终止速度比启动命令执行速度快,启动命令可能还是会被中断,所以方案1的独立脚本更稳妥。

方案3:使用Tomcat自带管理API重启(更优雅)

如果你的Tomcat开启了管理功能,可以通过Manager API触发重启,无需手动杀进程,安全性更高:

try {
    PreparedStatement.setQueryTimeout(10);
    rs = PreparedStatement.executeQuery();
} catch (SQLException ex) {
    System.out.println("IN CATCH BLOCK FOR THE REFRESH INVOICE");
    
    // 调用Tomcat Manager的重启API
    URL url = new URL("http://localhost:8080/manager/text/reload?path=/your-webapp");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("POST");
    // 设置管理账号密码(需在tomcat-users.xml配置manager-script权限)
    String userPass = "admin:your-password";
    String basicAuth = "Basic " + Base64.getEncoder().encodeToString(userPass.getBytes());
    conn.setRequestProperty("Authorization", basicAuth);
    
    int responseCode = conn.getResponseCode();
    if (responseCode == 200) {
        System.out.println("Tomcat restarted via Manager API");
    }
} catch (Exception e) {
    e.printStackTrace();
}

前提:你需要在tomcat-users.xml中配置具备manager-script权限的用户:

<user username="admin" password="your-password" roles="manager-script"/>

内容的提问来源于stack exchange,提问作者NewDeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:21:56