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

Linux下Java Process InputStream无输出问题排查

问题排查:ProcessBuilder执行lsof无输出的原因

以下是几个容易忽略的细节及解决方法:

1. 未处理错误输出流导致进程阻塞

ProcessBuilder启动的子进程,标准输出(stdout)和错误输出(stderr)是两个独立的缓冲区。终端中默认会将两者合并打印,所以你看不到区别;但Java代码里如果只读取stdout,当stderr缓冲区被填满时,子进程会被阻塞,无法继续向stdout输出内容。

解决方法:将stderr合并到stdout,或者单独开启线程读取stderr:

// 合并stderr到stdout,统一读取
builder.redirectErrorStream(true);

2. 未等待进程执行完成就销毁

你的代码在读取完输出后调用process.destroy(),但如果进程还未完全执行完毕,readLine()可能提前返回null,导致你错过输出。建议先等待进程执行结束:

// 等待进程执行完成,获取退出码
int exitCode = process.waitFor();

3. 运行权限不匹配

终端执行命令的用户与Java进程运行的用户权限可能不同。比如终端用root用户能正常获取PID,但Java进程以普通用户运行时,lsof会因权限不足向stderr输出错误信息,进而导致进程阻塞无输出。

可以检查Java进程的运行用户,或者尝试用sudo执行命令(需确保Java进程有sudo权限)。

4. 进程名称匹配不准确

终端中TestJar.jar可能是进程的短名称,但实际进程名可能包含完整路径。可以用以下命令确认进程的真实名称:

lsof -t -c java | xargs ps -p -o cmd=

如果是路径问题,修改lsof命令为精确匹配路径:

/usr/sbin/lsof -t /full/path/to/TestJar.jar

修改后的示例代码

try {
    ProcessBuilder builder = new ProcessBuilder("bash", "-c", "/usr/sbin/lsof -t TestJar.jar");
    builder.redirectErrorStream(true); // 合并错误输出到标准输出
    Process process = builder.start();
    
    // 等待进程执行完成
    int exitCode = process.waitFor();
    System.out.println("进程退出码: " + exitCode);
    
    System.out.println("----------------");
    BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
    String line;
    while((line = reader.readLine()) != null)
    {
        System.out.println(line);
    }
    
    reader.close();
    process.destroy();
    System.out.println("----------------");
}
catch(Exception e) 
{
    System.out.println("FAILED");
    Main.printToErrorLog(e);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 08:07:33