场景描述
使用 playwright-java进行页面快照截取,程序正常运行一段时间后,突然报错
Cannot run program "/tmp/playwright-java-639479522516008661/playwright.sh": error=2, No such file or directory
com.microsoft.playwright.PlaywrightException: Failed to launch driver
at com.microsoft.playwright.impl.PlaywrightImpl.create(PlaywrightImpl.java:50)
at com.microsoft.playwright.Playwright.create(Playwright.java:92)
at com.microsoft.playwright.Playwright.create(Playwright.java:96)
at com.ht.mile.stone.common.utils.snapshot.PlaywrightScreenshot.screenshot(PlaywrightScreenshot.java:46)
at com.ht.mile.stone.common.utils.snapshot.PlaywrightScreenshot.screenshotAndWatermark(PlaywrightScreenshot.java:31)
at com.ht.mile.stone.biz.task.DataReportTask.testPlayWright(DataReportTask.java:137)
at com.ht.mile.stone.biz.task.DataReportTask$$FastClassBySpringCGLIB$$514be944.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:102)
at com.ht.xxl_job.plus.JobAspect.interceptJobMethod(JobAspect.java:31)
at sun.reflect.GeneratedMethodAccessor965.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at com.ht.mile.stone.biz.task.DataReportTask$$EnhancerBySpringCGLIB$$3aa97a97.testPlayWright(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.xxl.job.core.handler.impl.MethodJobHandler.execute(MethodJobHandler.java:32)
at com.xxl.job.core.thread.JobThread.run(JobThread.java:166)
Caused by: java.io.IOException: Cannot run program "/tmp/playwright-java-639479522516008661/playwright.sh": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at com.microsoft.playwright.impl.PlaywrightImpl.create(PlaywrightImpl.java:43)
... 31 common frames omitted
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 32 common frames omitted
问题记录
1.查看tmp下,确实不存在playwright-java文件
2.查看创建源代码
类:com.microsoft.playwright.impl.Driver
private static Driver createDriver() throws Exception { String pathFromProperty = System.getProperty("playwright.cli.dir"); if (pathFromProperty != null) { return new PreinstalledDriver(Paths.get(pathFromProperty)); } Class<?> jarDriver = Class.forName("com.microsoft.playwright.impl.DriverJar"); return (Driver) jarDriver.getDeclaredConstructor().newInstance(); }源代码中优先获取了 System.getProperty("playwright.cli.dir") 配置,有可能是有可能首次调用创建了DriverJar,后续可能一些原因导致 tmp下文件被清理导致执行报错。
解决方案
方案1 - 重启项目
1.重启程序,重启后会重新生成该文件,问题修复
方案2 - 永久解决
升级最新版本 查看生成脚本的源码
类:com.microsoft.playwright.impl.driver.jar.DriverJar
版本: 1.60.0 public DriverJar() throws IOException { // Allow specifying custom path for the driver installation // See https://github.com/microsoft/playwright-java/issues/728 String alternativeTmpdir = System.getProperty("playwright.driver.tmpdir"); String prefix = "playwright-java-"; driverTempDir = alternativeTmpdir == null ? Files.createTempDirectory(prefix) : Files.createTempDirectory(Paths.get(alternativeTmpdir), prefix); driverTempDir.toFile().deleteOnExit(); String nodePath = System.getProperty("playwright.nodejs.path"); if (nodePath != null) { preinstalledNodePath = Paths.get(nodePath); if (!Files.exists(preinstalledNodePath)) { throw new RuntimeException("Invalid Node.js path specified: " + nodePath); } } logMessage("created DriverJar: " + driverTempDir); } 版本:1.17.2 DriverJar() throws IOException, URISyntaxException, InterruptedException { driverTempDir = Files.createTempDirectory("playwright-java-"); driverTempDir.toFile().deleteOnExit(); }新版中这里可以看到获取了生成文件的路径System.getProperty("playwright.driver.tmpdir");
在代码中手动指定路径 System.getProperty("playwright.driver.tmpdir","你的维护地址");
这样可以避免 /tmp路径下被系统清理的问题