Using Spring Boot 1.5.1.
The directory /tmp/tomcat-* are not deleted when stopping a Spring Boot application.
The directory is created using (in org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory) :
File tempDir = File.createTempFile(prefix + ".", "." + getPort());
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
return tempDir;
I think that deleteOnExit() method doesn't work if the directory is not empty. I made a little standard Java test:
public static void main(String[] args) throws IOException, InterruptedException {
File tempDir = File.createTempFile("prefix", "suffix");
tempDir.delete();
tempDir.mkdir();
tempDir.deleteOnExit();
try (FileOutputStream os = new FileOutputStream(new File(tempDir, "noempty.txt"))) {
os.write("This a not an empty file".getBytes());
}
Thread.sleep(Long.MAX_VALUE);
}
Then I send a linux signal kill -15 <pid> but the folder 'prefix*' is still here.
I think that deleteOnExit() method doesn't work if the directory is not empty
That's correct. We're simply making the best effort we can to clean up the directory when the JVM exits. Sometimes the directory won't be used so we can at least clean up the empty directory on exit. Beyond that, you should configure your OS's standard mechanism for cleaning up tmp when appropriate.
As mentionned on #5009, we cannot always use /tmp as a tomcat's temporary directory.
A JVM shutdown hook could resolve this issue
import org.springframework.util.FileSystemUtils;
...
Runtime.getRuntime().addShutdownHook(new Thread(() -> FileSystemUtils.deleteRecursively(tempDir)));
I can make a Pull Request, if you want.
As far as I know, there's nothing stopping you from using /tmp, you just need to configure the OS to only clean it up when appropriate.
A JVM shutdown hook could resolve this issue
Thanks for the suggestion, but if we always cleared out the whole directory on exit, we'd then get complaints from users who wanted it to remain. For example, users of JSPs may want the directory to remain so that unchanged JSPs don't need to be recompiled.
It would be really nice to be able to delete such folder if we wanted to: I find this very annoying as I sometimes restart my microservices very frequently, and I'd be perfectly fine with a shutdown hook written in my server code. Is there any way to know where such folder is created, or to provide spring boot with a hint where to create it? Please note that I cannot simply change the value of java.io.tmpdir to my liking, as other libraries are using it as well.
@bbossola server.tomcat.basedir controls the location. We only create a temp dir if that property isn't specified.
Thanks, that solves my issue :)
Tomcat. file is always generated in the TMP directory after the project is started. How to control how tomcat. file will not be generated in the TMP directory?
@jamesSkyDream That question has been answered by @snicoll two comments above yours:
https://github.com/spring-projects/spring-boot/issues/9983#issuecomment-355227395.
@wilkinsona I have found that the shutdown hook created by
is never effective since there are other directories that get created underneath that top level directory.
I am always left with the following directory tree
/tmp
\- tomcat.123456789.8080
\- work
\- Tomcat
\- localhost
\- ROOT
The directory tree is empty, but will not be cleaned up since the top level tomcat.* directory contains an empty directory. Perhaps a better way to do this would be to create a shutdown hook that would remove the entire directory tree if it does not contain any files.
That being said, I am not sure I understand what you mean by
Thanks for the suggestion, but if we always cleared out the whole directory on exit, we'd then get complaints from users who wanted it to remain. For example, users of JSPs may want the directory to remain so that unchanged JSPs don't need to be recompiled.
The directory created using File.createTempFile()
https://github.com/spring-projects/spring-boot/blob/b164b16c21734a8581b39553594f102a75bb9738/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/AbstractConfigurableWebServerFactory.java#L173
is guaranteed to be unique and will never be reused after the process exits so it should be safe to force deletion even if the directory does contain files.
is never effective since there are other directories that get created underneath that top level directory
This has already been discussed above
is guaranteed to be unique and will never be reused after the process exits
That's a good point. We could use recursive deletion only in the case where a temporary directory is being used rather than a user-configured directory. That said, I'm not convinced that the extra complexity is worthwhile. The OS already contains a mechanism for cleaning things up.
We'll have another look at this to see how tricky it might be.
When just deleting an empty directory the ordering of the deletion doesn't matter. If we start deleting the entire directory hierarchy including files that Tomcat has written, the ordering becomes important. That means that we can't use a shutdown hook as the hook that closes the context (and stops Tomcat) and the hook that deletes the directory hierarchy may run in any order or in parallel.
To implement this, I think we'd need to add something to the WebServer implementation that triggers the deletion of the temporary directory hierarchy as part of its stop processing.
Ergh. I think we should push this back then. It's not too urgent for 2.2.x
Thanks, we are facing the same issue where many of these empty folders are created for each test run and not deleted
I was facing the same issue with the login (Spring security), on Windows tho , i've been on it for hours. At first I deleted all temp/tomcat/ with no result
And then i killed the pid in windows using "taskkill /PID
To get the PID, check your console
Most helpful comment
@wilkinsona I have found that the shutdown hook created by
https://github.com/spring-projects/spring-boot/blob/b164b16c21734a8581b39553594f102a75bb9738/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/AbstractConfigurableWebServerFactory.java#L176
is never effective since there are other directories that get created underneath that top level directory.
I am always left with the following directory tree
The directory tree is empty, but will not be cleaned up since the top level tomcat.* directory contains an empty directory. Perhaps a better way to do this would be to create a shutdown hook that would remove the entire directory tree if it does not contain any files.
That being said, I am not sure I understand what you mean by
The directory created using
File.createTempFile()https://github.com/spring-projects/spring-boot/blob/b164b16c21734a8581b39553594f102a75bb9738/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/server/AbstractConfigurableWebServerFactory.java#L173
is guaranteed to be unique and will never be reused after the process exits so it should be safe to force deletion even if the directory does contain files.