java -jar 启动Springboot线上报错FileNotFoundException

发现问题

今天在将项目打包放在线上后,遇到了一个问题,错误堆栈如下:

java.io.FileNotFoundException: /tmp/tomcat.3411451253170172517.9998/work/Tomcat/localhost/ROOT/upload_95a9f6c4_32ff_4372_a19b_c447216971a3_00000017.tmp (No such file or directory)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.<init>(FileInputStream.java:138)
	at org.apache.tomcat.util.http.fileupload.disk.DiskFileItem.getInputStream(DiskFileItem.java:194)
	at org.apache.catalina.core.ApplicationPart.getInputStream(ApplicationPart.java:100)
	at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile.getInputStream(StandardMultipartHttpServletRequest.java:250)
	at cn.anytec.anguan.util.SpringAsyncUtil.analyseDataPersistence(SpringAsyncUtil.java:33)
	at cn.anytec.anguan.util.SpringAsyncUtil$$FastClassBySpringCGLIB$$9155c306.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.lang.Thread.run(Thread.java:748)

分析问题

代码逻辑主要是将摄像头传递过来的图片进行保存,在开发机win上面没有问题,并且在Linux线上,第一次报错第二次不会报错,成功运行。

寻找解决方案

问题比较离奇,遂Google寻找解决方案。

发现已经有大神遇到过此问题,并且给出了完整的解决方案和错误原理分析。
链接:superlovelei

解决方案及总结

虽然大神已经给出了原因,我再次再做一次表述吧。
在Linux系统中,通过java -jar 运行的项目,会在操作系统的 /tmp/tomcat... 目录下新建一个目录,上传的文件都会先临时存放在此,而由于linux的系统机制,如果超过10天没有操作过此文件目录,会将目录删除,所以如果当前linux主机第一次运行上传相关的程序或者很久(超过10天)没有操作过此临时目录,就会出现报错。

而通过配置springboot的yml文件,修改server的配置文件,手动指定临时目录(不会被机制删除的路径),此问题就迎刃而解。

server:
  tomcat:
    basedir: /tmp