首页 文章

从java进程生成tar文件时tar命令卡住了

提问于
浏览
2

使用Runtime exec() 方法在命令下运行,以使用java生成目录的tar

tar -zcvf dest.tar.gz -C dirTotar .

用于tar创建的Java代码

String command = "tar -zcvf dest.tar.gz -C dirTotar .";
    Process process = Runtime.getRuntime().exec(command);
    process.waitFor()
    return process.exitValue();

Java进程是在每次输入后处理后创建tar文件的服务器 . 处理少量输入后,进程停留在tar步骤 .

strace -p 找到进程是否卡住,它显示在输出下方

strace -p 6782 
Process 6782 attached - interrupt to quit 
write(1, "./file"..., 66

我为输入目录手动运行了tar命令,它运行正常 . 任何指针为什么会发生这种情况?

Update:

对于如下目录结构

/tmp/dir1
/tmp/dir2
/tmp/dir3
.
.

由进程生成tar的目录是dir1 . 还有其他进程为dir2,dir3生成tar ...

当为dir1生成tar的进程被卡住时,另一个尝试tar其他目录(dir2,dir3)的进程也被卡住了 . 这可能是问题的原因吗?

1 回答

  • 1

    事实1: tar zcv... 输出到每个文件的stdout,它存档包含该文件的文件名的行 . 此行的长度取决于文件名,此输出的总长度取决于文件的数量和文件名的总长度 .

    事实2:由Java运行的进程 Runtime.exec 将其stdout定向到管道,该管道的另一端提供给Java程序,因此Java代码可以读取进程的输出 . (对于stderr也是如此,对于stdin来说也是如此,但是他们并没有读取这个管道 .

    事实3:当进程(例如 tar )写入管道而没有从该管道的另一端读取任何内容时,当管道缓冲区填满写入进程时会挂起 . 你的 strace 显示 tar (显然是悬挂在) write 到fd 1是stdout . 管道缓冲区的大小可能因系统而异,有时还有其他因素,但通常是几K字节,这取决于您要归档的文件的名称,可能是几十到几百个文件名 .

    Solution: 要么更改代码以读取 tar 的输出 - 请参阅Process.getInputStream() - 或更改命令(通过删除 v ),以便它不会产生(非错误)输出 .

    PS:正如javadoc中所提到的,自Java 5以来首选ProcessBuilder . 默认情况下,它也使用来自新进程的管道,但是自Java 7以来有(几种)方法来改变它 .

相关问题