Метод выполнения командной строки Apache commons возвращает код выхода -1 при запуске в приложении tomcat и вызывает исключение ExecuteException

#java #command-line #tomcat8 #apache-commons

Вопрос:

Используя библиотеку командной строки Aapche commons, я пытаюсь выполнить команду openssl в веб-приложении, работающем в tomcat в ОС SLES. ниже приведен фрагмент кода —

      CommandLine cmd = new CommandLine("/usr/bin/openssl")
                .addArgument("genrsa")
                .addArgument("-out")
                .addArgument("/root/testcert_tomcat.key")
                .addArgument("4096");
        logger.info("Command - "  cmd.toString());

        DefaultExecutor executor = new DefaultExecutor();
        executor.setProcessDestroyer(new ShutdownHookProcessDestroyer());
        executor.setStreamHandler(new PumpStreamHandler(null, null, null));
        executor.setWatchdog(new ExecuteWatchdog(60000));
        executor.setExitValue(0);
        try {
            int exitValue = executor.execute(cmd);
            if(exitValue != 0 ){
               logger.info("Exit value  - "  exitValue);
            }
        } catch (IOException ex) {
            logger.info("Exception - "  ex.getMessage());

            return false;
        } 
 

команда — тест openssl genrsa -out.ключ 4096

та же команда отлично работает при запуске из обычного кода java вне веб-приложения tomcat или непосредственно из командной строки оболочки. Если у кого-то есть какие-либо идеи, пожалуйста, предложите, в чем может быть проблема.

Поймано исключение — org.apache.commons.exec.Исключение ExecuteException: Процесс завершен с ошибкой: 1 (значение выхода: 1)

Не совсем уверен, но я попытался проверить пользователя tomcat, он работает от имени root —

 libv222:/usr/share/tomcat/webapps # ps auxwww | grep -v grep | grep tomcat

tomcat   13700 27.7 12.3 3610620 498412 ?      Ssl  20:20   0:46 /usr/bin/java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=5000,suspend=n -XX: HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -Djava.security.auth.login.config=/usr/share/tomcat/conf/jaas.config -Djava.library.path=/lib/emc/powerpath/remote_tools/latest/ -XX:MaxPermSize=128M -Xms512m -Xmx1536m -classpath /usr/share/tomcat/bin/bootstrap.jar:/usr/share/tomcat/bin/tomcat-juli.jar:/usr/share/java/commons-daemon.jar -Dcatalina.base=/usr/share/tomcat -Dcatalina.home=/usr/share/tomcat -Djava.endorsed.dirs= -Djava.io.tmpdir=/var/cache/tomcat/temp -Djava.util.logging.config.file=/usr/share/tomcat/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager org.apache.catalina.startup.Bootstrap start

root     16591  0.0  0.0   4244   728 pts/0    S    17:34   0:00 tail -f /var/log/tomcat/catalina.out
 

Комментарии:

1. Можете ли вы включить в свой вопрос исключение, которое вы получаете? Вероятно, у вас проблема с разрешениями, так как Tomcat обычно не запускается от имени, root а /root папка недоступна для записи другими пользователями.

2. Предложение: Вы можете зарегистрировать полную трассировку стека ex , а не только сообщение. Часто в полной трассировке можно найти полезную информацию.

3. Обновил трассировку исключений, получив только исключение в трассировке. Можно ли запустить tomcat от имени root, чтобы проверить это поведение ?

4. Вместо того, чтобы запускать его как root (что, безусловно, возможно), запишите закрытый ключ в доступную папку ( /tmp/testcert_tomcat.key например) или измените разрешение папок, чтобы разрешить запись tomcat пользователем.

5. Он работал как корень и изменение разрешений при написании ключа на самом деле помогло в предыдущем случае, но когда я изменил команду openssl на — « openssl x509-req-in /tmp/ppserver.csr-out /tmp/ppserver.crt-sha256-CA /tmp/powerpath-CA.crt-CAkey /tmp/powerpath-CA.ключ-CAcreateserial-дней 821` » вызвал ту же ошибку, даже у меня теперь есть разрешения на папки. Выполнение этой команды с помощью apache common exec создает пустой файл ppserver.crt и возвращает код выхода 1.

Ответ №1:

Приведенный ниже код работал на меня, мне пришлось переключиться с Apache commons на создание процесса, чтобы заставить его работать. Похоже, для успешного выполнения нам нужно выполнить эту команду в новом процессе.

Люди предположили в комментариях, что каталог должен иметь доступ для чтения и записи везде, где это необходимо, что, безусловно, необходимо для выполнения команд.

 private static boolean executeOpenSslCmdProcess(String host) {

        StringBuffer command = new StringBuffer();
        command.append("openssl x509 -req -in /tmp/ppserver.csr -out /tmp/ppserver.crt -sha256 -CA /tmp/powerpath-CA.crt -CAkey /tmp/powerpath-CA.key -CAcreateserial -days 821");
        String[] cmd = {
            "/bin/sh",
            "-c",
            command.toString()
        };
        try {

            Process process = Runtime.getRuntime().exec(cmd);
            InputStream inputStream = process.getInputStream();

            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, CHAR_SET));
            result = br.lines().collect(Collectors.joining(System.lineSeparator()));

            exitCode = process.waitFor();
            logger.info("ExitCode : {} ", exitCode);
            if (exitCode != 0) {
                return false;
            }
        } catch (IOException ex) {
            logger.info("IOException - "   ex);
            return false;
        } catch (InterruptedException ex) {
            logger.info("InterruptedException - "   ex);
        }
}
 

Спасибо за предложения в комментариях!