[英]Gradle unable to write sysout to file - java.io.IOException: Unable to delete file
I am trying to put output of a command to some file.我正在尝试将命令的输出放入某个文件。 Before writing the file i want to delete the file and than do write operation.在写入文件之前,我想删除文件而不是进行写入操作。 Here is my gradle script这是我的gradle脚本
group 'org.example'
version '1.0-SNAPSHOT'
task deletefiles(type: Delete){
delete "$projectDir/somefile.txt"
}
task writefile(type: Exec, dependsOn: deletefiles){
commandLine 'echo', "Hello World"
standardOutput = new FileOutputStream("$projectDir/somefile.txt")
}
But when i run writefile tasks , I get below error但是当我运行 writefile 任务时,出现以下错误
Execution failed for task ':deletefiles'.
> java.io.IOException: Unable to delete file 'D:\workspace\code\repo\sample-gradle-mono\somefile.txt'
Any idea what's wrong?知道出了什么问题吗?
One thing i guess is that gradle is somehow acquiring lock on file before deletefiles tasks could start.我猜的一件事是 gradle 在deletefiles任务可以开始之前以某种方式获取文件锁定。 If that is the case, How can we achieve this?如果是这样,我们如何才能实现这一目标?
Edit 1: Enviroment info -编辑 1:环境信息 -
------------------------------------------------------------
Gradle 6.3
------------------------------------------------------------
Build time: 2020-03-24 19:52:07 UTC
Revision: bacd40b727b0130eeac8855ae3f9fd9a0b207c60
Kotlin: 1.3.70
Groovy: 2.5.10
Ant: Apache Ant(TM) version 1.10.7 compiled on September 1 2019
JVM: 11.0.4 (Oracle Corporation 11.0.4+11)
OS: Windows 10 10.0 amd64
the problem that in your gradle the following line executed at project configuration phase在项目配置阶段在您的 gradle 中执行以下行的问题
standardOutput = new FileOutputStream("$projectDir/somefile.txt")
it means that stream is created and file locked even before any gradle task was started..这意味着即使在启动任何 gradle 任务之前,流已被创建并被锁定。
try this groovy configuration to see the issue:尝试这个 groovy 配置以查看问题:
class MyStream extends FileOutputStream{
MyStream(String f){
super(f)
println "write $f stream created"
}
}
task deletefiles(type: Delete){
println "delete init"
doFirst{
println "delete doFirst" //triggered just before deletion
}
delete "out.txt"
}
task writefile(type: Exec, dependsOn: deletefiles){
println "write init"
commandLine 'cmd', '/C', 'echo', "Hello World"
standardOutput = new MyStream("out.txt")
}
in output you can see that stream is created before tasks execution:在输出中,您可以看到在任务执行之前创建了流:
cmd> gradle writeFile
> Configure project :
delete init
write init
write out.txt stream created
> Task :deletefiles FAILED
delete doFirst
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':deletefiles'.
> java.io.IOException: Unable to delete file 'out.txt'
To fix it - define the standardOutput
just before the "Exec" task is executed:要修复它- 在执行“Exec”任务之前定义standardOutput
:
class MyStream extends FileOutputStream{
MyStream(String f){
super(f)
println "write $f stream created"
}
}
task deletefiles(type: Delete){
println "delete init"
doFirst{
println "delete doFirst"
}
delete "out.txt"
}
task writefile(type: Exec, dependsOn: deletefiles){
println "write init"
commandLine 'cmd', '/C', 'echo', "Hello World"
doFirst{
println "write doFirst"
standardOutput = new MyStream("out.txt")
}
doLast{
println "write doLast"
}
}
output:输出:
cmd>gradle writeFile
> Configure project :
delete init
write init
> Task :deletefiles
delete doFirst
> Task :writefile
write doFirst
write out.txt stream created
write doLast
BUILD SUCCESSFUL in 3s
2 actionable tasks: 2 executed
to add some clarity :增加一些清晰度:
for example the this task definition例如这个任务定义
task writefile(type: Exec, dependsOn: deletefiles){
println "write init"
commandLine 'cmd', '/C', 'echo', "Hello World"
doFirst{
println "write doFirst"
standardOutput = new MyStream("out.txt")
}
doLast{
println "write doLast"
}
}
you could replace with the following groovy code in your gradle:您可以在您的 gradle 中替换为以下 groovy 代码:
def writefile = project.task( [type: Exec, dependsOn: deletefiles], 'writeFile' )
println "write init"
writefile.setCommandLine( ['cmd', '/C', 'echo', "Hello World"] )
writefile.getActions().add( 0, {
//those commands will be executed later when task `writefile` decided to be executed by gradle
println "write doFirst"
writefile.standardOutput = new FileOutputStream("out.txt")
} as Action)
writefile.getActions().add( {
//those commands will be executed later when task `writefile` decided to be executed by gradle
println "write doLast"
} as Action)
links to official documentation that could explain this behavior:可以解释这种行为的官方文档链接:
https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:settings_file https://docs.gradle.org/current/userguide/build_lifecycle.html#sec:settings_file
https://docs.gradle.org/current/userguide/more_about_tasks.html https://docs.gradle.org/current/userguide/more_about_tasks.html
It is possible that something is holding the file open.可能是某些东西使文件保持打开状态。 Sometimes if IO streams are not properly closed this can happen.有时,如果 IO 流没有正确关闭,就会发生这种情况。 Gradle docs say that exec task closes the output stream after the process terminates, so that shouldn't be the problem. Gradle 文档说 exec 任务在进程终止后关闭输出流,所以这应该不是问题。 It could be a known issue with deleting on Windows.在 Windows 上删除可能是一个已知问题。 Eg: https://carlrice.io/blog/gradle-clean-cant-delete-file-on-windows例如: https : //carlrice.io/blog/gradle-clean-cant-delete-file-on-windows
https://github.com/gradle/gradle/issues/9813 (but that one is about folders) https://github.com/gradle/gradle/issues/9813 (但那个是关于文件夹的)
https://www.eknori.de/2020-09-18/gradle-execution-failed-for-task-appclean-unable-to-delete-file/ https://www.eknori.de/2020-09-18/gradle-execution-failed-for-task-appclean-unable-to-delete-file/
I would run the build with --debug to capture more details of the exception.我将使用 --debug 运行构建以捕获异常的更多详细信息。
Are you running with the Gradle daemon?你在运行 Gradle 守护进程吗? Try without it.没有它试试。 Since it is a persistent process, maybe for some reason it has a file handle open to that file.由于它是一个持久进程,可能出于某种原因它有一个打开该文件的文件句柄。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.