提问人:user12345 提问时间:10/20/2023 更新时间:10/20/2023 访问量:78
Java - 无法在 Windows 上删除 Process 的临时输出文件
Java - Unable to delete temporary output file for Process on Windows
问:
在 Windows 上,我通过 .如果我的调用函数中断,在尝试清理进程及其标准输出日志文件时,我收到错误“进程无法访问该文件,因为它正在被另一个进程使用”。我确保先销毁子进程,然后删除日志文件。java.lang.ProcessBuilder
问题 - 在清理与平台无关的进程和日志文件时,是否有任何最佳实践?
下面是 Windows 的可重现示例。
下面的代码片段正在创建一个子进程。
public class UndeletableFileExample {
public static void func() throws IOException {
ProcessBuilder pb = null;
Path stdout = null;
Process p = null;
long bufferTimeSecs = 30L;
try {
stdout = Files.createTempFile("example", ".log");
pb = new ProcessBuilder("loop.cmd");
pb.redirectErrorStream(true);
pb.redirectOutput(stdout.toFile());
p = pb.start();
p.waitFor(bufferTimeSecs, TimeUnit.SECONDS);
p.destroy();
p.waitFor(bufferTimeSecs, TimeUnit.SECONDS);
p.destroyForcibly();
String out = Files.readString(stdout);
int exitcode = p.exitValue();
if(exitcode != 0) {
throw new RuntimeException("Exited with code " + exitcode);
}
System.out.println(out);
}
catch(InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("interrupted!");
}
finally {
if(p != null) {
p = p.destroyForcibly();
while(p.isAlive()); // Is this while loop a potential problem?
System.out.println(p.exitValue());
}
if(stdout != null) {
Files.delete(stdout);
}
}
}
}
下面的代码片段是 for 循环文件“loop.cmd”。它将打印从 1 到 1e5 的数字。这在我的机器上需要 20-30 秒。
FOR /L %%i IN (1,1,100000) DO echo %%i
以下代码片段是执行模拟的主程序。
public class Demo {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
@Override
public void run() {
try {
UndeletableFileExample.func();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
t.start();
Thread.sleep(2000L);
t.interrupt();
t.join();
}
}
我还可以访问 MacOS 计算机。在清理进程和线程中断上的日志文件时,我没有遇到任何问题。
MacOS 的循环示例更改为 -
for i in `seq 1 1000000`; do echo $i; done
Windows 上的确切错误如下 -
Exception in thread "Thread-0" java.lang.RuntimeException: java.nio.file.FileSystemException: <...>\example1234.log: The process cannot access the file because it is being used by another process.
答: 暂无答案
评论
while (p.isAlive()) { Thread.onSpinWait(); }
11.0.19+9
for(int i = 0; i < 1000000; i++);Files.delete(stdout);