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

Tomcat部署WAR文件时Java Jsch会话遭Linux权限拒绝的原因

问题:Tomcat部署WAR后JSch连接失败(Permission Denied)

本地测试(直接运行Java类)和服务器手动执行java RunClass时,JSch能正常建立会话执行shell脚本;但打包成WAR部署到同一服务器的Tomcat 7.0.76后,调用接口触发session.connect()或channelExec.connect()时抛出:

java.net.SocketException : Permission Denied, Connect Failed

此前使用ProcessBuilder也存在类似问题:本地可正常执行命令,Tomcat部署后提示Permission Denied, Cannot Execute command chmod(或conda命令)。

相关代码

Controller.java

@RequestMapping(value="/endpoint", method=RequestMethod.GET)
public ResponseEntity<String> generateOrderTrail2(@RequestParam("id") String id){

    ScriptCaller scriptCaller = new ScriptCaller();
    scriptCaller.setId(id);
    scriptCaller.executeCommand();

    if(scriptCaller.isSuccessful()){
        return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body("Successful");
    }
    else{
        return ResponseEntity.badRequest().contentType(MediaType.APPLICATION_JSON).body("Unsuccessful");
    }

}

ScriptCaller.java

boolean isSuccessful = false;
public void executeCommand(){
    String command = './dir/folder/executeFile.sh';
    try{
        JSch jsch = new JSch();
        Session session = jsch.getSession(this.username, this.hostname, 22);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);

        session.setPassword(this.password);
        session.connect();
        StringBuilder output = new StringBuilder("");
        ChannelExec channelExec = (ChannelExec) session.openChannel("exec");
        channelExec.setInputStream((InputStream)null);
        InputStreamReader stream = new InputStreamReader(channelExec.getInputStream());
        channelExec.setInputStream((InputStream) null);
        channelExec.setCommand(command);
        channelExec.connect();
        char[] buffer = new char[128];
        int read;
        while ((read=stream.read(buffer, 0, buffer.length))>=0){
            output.append(buffer, 0, read);
        }
        this.callerResponse = output.toString();
        int exitCode = channelExec.getExitStatus();
        channelExec.disconnect();
        session.disconnect();
        if(exitCode == 0){
            System.out.println("Shell Script Executed Successfully");
            isSuccessful = true;
        }
        else{
            System.out.println("Shell Script Failed to Execute");
            isSuccessful = false;
        }
    }
    catch(Exception e){
        e.printStackTrace();
        isSuccessful = false;
    }
}

构建与异常信息

Maven构建命令:

mvn clean deploy -Denvironment=local -Dskip.webapp=true -Dmaven.test.skip=true

异常栈关键信息:

java.net.SocketException: Permission Denied(connect failed)
..
..
at com.jcraft.jsch.Util.createSocket(Util.java)

已确认:shell文件权限为777,同一用户本地/手动运行Java类正常,仅Tomcat部署后触发权限拒绝。


原因分析

1. Tomcat运行用户与手动执行用户不一致

Tomcat通常以专用系统用户(如tomcat、www-data)运行,和你手动执行Java类的登录用户不是同一身份。即便脚本设为777,Tomcat用户可能被系统限制:

  • 无出站网络连接权限(防火墙/安全策略禁止该用户发起SSH连接)
  • 无脚本所在父目录的x权限(无法进入目录访问脚本)

2. SELinux/AppArmor安全策略拦截

多数Linux服务器启用SELinux或AppArmor,这类安全框架会限制服务进程的操作:

  • 默认禁止Tomcat进程发起SSH连接
  • 限制Tomcat执行chmod、conda等系统/第三方命令

3. Tomcat安全管理器权限限制

Tomcat 7默认可能启用安全管理器(SecurityManager),其catalina.policy配置文件未授予程序:

  • 发起网络连接的权限
  • 执行系统命令、访问指定文件的权限

4. 环境变量差异

手动运行Java类时使用当前用户的完整环境变量,而Tomcat启动时会重置环境变量,导致conda等命令的路径未被加载,实际是命令找不到,但错误提示被混淆为权限问题。


排查与解决建议

  1. 确认Tomcat运行用户
    执行ps aux | grep tomcat查看Tomcat的运行用户,切换到该用户手动执行java RunClass,验证是否复现问题。

  2. 检查SELinux/AppArmor状态

    • 执行getenforce查看SELinux是否开启,临时关闭setenforce 0测试是否恢复正常;若正常,需添加SELinux策略允许Tomcat发起SSH连接。
    • 若使用AppArmor,检查Tomcat的配置文件是否限制了网络或命令执行。
  3. 调整Tomcat安全管理器权限
    若启用了安全管理器,在conf/catalina.policy中添加对应权限(替换your-war-name为实际WAR包名):

    grant codeBase "file:${catalina.base}/webapps/your-war-name/-" {
        permission java.net.SocketPermission "*:22", "connect,resolve";
        permission java.io.FilePermission "/dir/folder/executeFile.sh", "execute";
    };
    
  4. 统一Tomcat环境变量
    在Tomcat的bin/setenv.sh中添加conda等命令的路径:

    export PATH=/path/to/conda/bin:$PATH
    
  5. 检查父目录权限
    确保脚本所在的/dir/folder/父目录给Tomcat用户分配了x权限(允许进入目录),执行chmod o+x /dir/folder/测试。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:35:00