0

I have a problem with executing command in Runtime.getRuntime().exec(command) on my linux DEV machine. I'm trying to convert html content to mobi format using calibre but it doesn't work. Even if I added log.warn to display what this process returns it shows nothing.

It works on my local machine where I do have Windows 10 and I read on the Internet that I should point out that command should be launched on linux so I added String[] cmd = {"bash", "-c", command}; but it still doesn't work.

My command looks like this:

/usr/src/calibre/ebook-convert /tmp/filesDirectory_mobi3970575619159760977/d7ed6792-b3cb-4761-bb6a-b9facf9e7a6c9250643820137116550.html /tmp/filesDirectory_mobi3970575619159760977/d7ed6792-b3cb-4761-bb6a-b9facf9e7a6c11909891397415910433.mobi

And here's my code:

@Override
    public Document convert(Document document, DocumentFormat documentFormat) {
        Document htmlDocument = htmlDocumentConverter.convert(document, documentFormat);
        try {
            log.info("Converting document from {} to {}", getSourceFormat().toString(), getTargetFormat().toString());
            CalibreConfigData calibreData = calibreConfig.getConfigurationData(CalibreConversion.HTML_TO_MOBI);

            Files.write(calibreData.getSourceFilePath(), htmlDocument.getContent());

            String command = calibreData.getCalibreCommand();
            String[] cmd = {"bash", "-c", command};
            var r = Runtime.getRuntime().exec(cmd);
            r.waitFor();
            log.warn("Process: " + new String(r.getInputStream().readAllBytes(), StandardCharsets.UTF_8));

            byte[] convertedFileAsBytes = Files.readAllBytes(calibreData.getConvertedFilePath());

//            Files.deleteIfExists(calibreData.getSourceFilePath());
//            Files.deleteIfExists(calibreData.getConvertedFilePath());
//            Files.deleteIfExists(calibreData.getFilesDirectoryPath());

            return new Document(convertedFileAsBytes);
        } catch (InterruptedException | IOException e) {
            log.error("Conversion failed due to problem: " + e);
            throw new ConversionException("Conversion failed due to problem: " + e);
        }
    }

I checked created tempFiles and found out that file .html has content inside but file .mobi is empty even after executing above's command.

oguz ismail
  • 1
  • 16
  • 47
  • 69
me_how
  • 23
  • 5
  • 1
    I don't get it. It looks like you're using some sort of Calibre API there, yet you're still using `Runtime.exec` - why? – g00se Nov 13 '22 at 16:59
  • The "*command*" you provided does not look like a command, but two file paths. – Turing85 Nov 13 '22 at 16:59
  • In general, you should regard `Runtime.exec` as legacy and stick to `ProcessBuilder`. In particular, the latter makes it tons easier to deal with the streams produced by the `Process` and that is pretty likely your problem here. You need to consume stdout and stderr – g00se Nov 13 '22 at 17:04

1 Answers1

1

A main method of a Calibre conversion invoker could be as simple as the below:

public static void main(String[] args) {
    try {
        String[] command = { "/usr/src/calibre/ebook-convert", args[0], args[1] };
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.inheritIO();
        pb.start();
    } catch (Throwable t) {
        t.printStackTrace();
    }
}
g00se
  • 3,207
  • 2
  • 5
  • 9