首页 > 解决方案 > 无法运行程序“wkhtmltopdf”:错误=2,没有这样的文件或目录 - 从 Java 获取此错误

问题描述

我正在从 Java 执行 wkhtmltopdf 命令行工具,但它抛出错误。

Cannot run program "wkhtmltopdf": error=2, No such file or directory

但请注意,当我从我的 mac 终端执行此命令行工具时,pdf 已成功生成。请看下文。

MacBook-Air-2:~ inDiscover$ wkhtmltopdf /var/folders/7y/2vr28n113p908ksnk0fnpqch0000gn/T/test7896850081571855407.html /Users/mymac/Documents/Project/emailbody/test2.pdf
Loading pages (1/6)
Counting pages (2/6)                                               
Resolving links (4/6)                                                       
Loading headers and footers (5/6)                                           
Printing pages (6/6)
Done

我在这里看到了很多类似的问题(例如:wkhtmltopdf:没有这样的文件或目录 [已关闭]),但这些问题的问题与$PATH. 就我而言,我相信我已将可执行文件的路径设置为$PATH正确。请看下文。

MacBook-Air-2:~ inDiscover$ locate wkhtmltopdf
/private/var/db/receipts/org.wkhtmltopdf.wkhtmltox.bom
/private/var/db/receipts/org.wkhtmltopdf.wkhtmltox.plist
/usr/local/bin/wkhtmltopdf
/usr/local/share/man/man1/wkhtmltopdf.1.gz

可以看到这里wkhtmltopdf已经添加到$PATH(/usr/local/bin)

此外,请参阅下面的响应echo $PATH

MacBook-Air-2:~ inDiscover$ echo $PATH
/Users/mymac/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
MacBook-Air-2:~ inDiscover$ 

仅当我尝试从 Java 执行命令时才遇到此问题。请在下面查看我的 java 代码。

String VIEWPORT_SIZE = "2480x3508";
        int CONVERSION_DPI = 300;
        int IMAGE_QUALITY = 100;
        
        List<String> cmd = new ArrayList<String>(Arrays.asList("wkhtmltopdf",
                "--viewport-size", VIEWPORT_SIZE,
                "--enable-local-file-access",
                // "--disable-smart-shrinking",
                "--dpi", String.valueOf(CONVERSION_DPI),
                "--image-quality", String.valueOf(IMAGE_QUALITY)));
        //cmd.addAll(extParams);
        cmd.add("/var/folders/7y/2vr28n113p908ksnk0fnpqch0000gn/T/test7896850081571855407.html");
        cmd.add("/Users/mymac/Documents/Project/emailbody/test3.pdf");
        
        
        try {
            ProcessBuilder pb = new ProcessBuilder(cmd);

            if (Logger.level.compareTo(LogLevel.Info) >= 0) {
                pb.inheritIO();
            }

            Process p = pb.start();
            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }

我真的错过了什么吗?

标签: javawkhtmltopdf

解决方案


您可以检查以下几件事,希望能解决您的问题。

几乎所有我见过的 java 没有找到你的 shell 或终端运行的应用程序的情况都归结为使用了 shell / 终端中内置的命令(例如别名),或者因为你在脚本中使用了 PATH用于启动您java yourapp.ClassName ...的与交互式外壳/终端的设置不同。

交互式 shell / 终端可能在启动时包含其他脚本或从其他脚本获取源 - 例如,它可能在~/.bashrc, ~/.login, ~/.profile, ... 中运行代码,这意味着在交互式 shell 中声明的 PATH 与启动时呈现给 Java 应用程序的 PATH 不同。

因此,您会看到终端显示 PATH 有 /usr/local/bin:

MacBook-Air-2:~ inDiscover$ echo $PATH
/Users/mymac/anaconda/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

但是Java在PATH中说没有/usr/local/bin:

System.out.println("PATH="+System.getenv("PATH"));
/usr/bin:/usr/sbin:/sbin

因此,要解决您的问题,您可以让 java 使用绝对路径来运行应用程序 wkhtmltopdf:

Arrays.asList("wkhtmltopdf" ->  Arrays.asList("/usr/local/bin/wkhtmltopdf" ...

或者您可以让 java 启动您的 shell / 终端,以便终端正常获取其 env 脚本并运行命令:

# Confirm which shell your Terminal uses:
echo $SHELL

如果你说SHELL=/bin/bash你可以/bin/bash从 java 运行并让它找出 wkhtmltopdf 的位置:

Arrays.asList("wkhtmltopdf" ->  Arrays.asList("/bin/bash", "-c", "wkhtmltopdf" ...

或者,如果您有一个脚本说runMyApp.sh要启动您的 java 应用程序,请在 PATH 之前设置java yourclass.Name

export PATH=/usr/local/bin:$PATH
java yourclass.Name

或者,如果您有一个脚本说runMyApp.sh要启动您的 java 应用程序,请使其与您的终端具有相同的配置文件环境。这取决于 SHELL,但对于某些系统可能类似于:

#!/bin/bash

# Load env from current user - "source" and "." may or may not work in the SHELL you are using:
source ~/.bashrc
# OR maybe other shell
. ~/.somefilerc

echo $PATH # Now hopefully includes same /usr/local/bin
java yourclass.Name

推荐阅读