使用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:
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以来有(几种)方法来改变它 .