Выполнение linux mutt из Java Runtime.getRuntime не отправляет почту и не выдает ошибку - PullRequest
0 голосов
/ 04 марта 2019

Я пытаюсь отправить письмо с помощью Mutt в Linux и Java, если я выполняю команду Mutt из командной строки Linux, электронная почта отправляет отлично

echo "test" | mutt -s "subject" -- "jojo@foo.com

Теперь у меня есть это простое приложение Java, которое я пытаюсь выполнитьта же команда, и я ничего не получаю, даже ошибки:

java -cp runtime-SNAPSHOT.jar MyApp "echo \"test\" | mutt -s \"subject\"  \"jojo@foo.com\""

class StreamGobbler extends Thread
{
    InputStream is;
    String type;

    StreamGobbler(InputStream is, String type)
    {
        this.is = is;
        this.type = type;
    }

    public void run()
    {
        try
        {
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null)
                System.out.println(type + ">" + line);
        } catch (IOException ioe)
        {
            ioe.printStackTrace();
        }
    }
}
public class MyApp {

    public static void main(String[] args) throws InterruptedException, IOException {

        if (args.length < 1)
        {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }
        try
        {
            String[] cmd = new String[3];
            Runtime rt = Runtime.getRuntime();
            System.out.println("Execing " + args[0] );
            Process proc = rt.exec(args[0]);
            // any error message?
            StreamGobbler errorGobbler = new
            StreamGobbler(proc.getErrorStream(), "ERROR");
            // any output?
            StreamGobbler outputGobbler = new
            StreamGobbler(proc.getInputStream(), "OUTPUT");
            // kick them off
            errorGobbler.start();
            outputGobbler.start();
            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);
        } catch (Throwable t)
        {
            t.printStackTrace();
        }
}

что здесь не так?

1 Ответ

0 голосов
/ 04 марта 2019

Вы не получаете ошибки, так как эхо, кажется, доступно в вашей системе (обычно это "/ bin / echo").Stringtokenizer в exec-методе Runtime передает оставшуюся часть строки в качестве параметров в / bin / echo следующим образом:

/bin/echo "\"test\"" "|" "mutt" "-s" "\"subject\"" "--" "\"jojo@foo.com\""

Ну, это действительная команда, так как она вызывает / bin / echo и / bin / echoвыводит все параметры, но никогда не вызывает Mutt.(кстати. / bin / echo - это эхо, отличное от того, которое используется в оболочке Bash, которое является встроенным и ведет себя немного иначе ...)

То, что они (Java) маркируют команду в методе execиногда это может быть удобно, но приводит к довольно раздражающим эффектам, подобным этому, потому что можно предположить, что что-то должно работать, что на самом деле не так, как в этом случае ...

Что вам, вероятно, нужно, это оболочка, выполняющая вашу командулиния.Таким образом, вы должны фактически выполнить оболочку (я отметил изменение в файле):

public class MyApp {

    static class StreamGobbler extends Thread {

        InputStream is;
        String type;

        StreamGobbler(InputStream is, String type) {
            this.is = is;
            this.type = type;
        }

        public void run() {
            try {
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null) {
                    System.out.println(type + ">" + line);
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException, IOException {

        /*if (args.length < 1) {
            System.out.println("USAGE: java GoodWindowsExec <cmd>");
            System.exit(1);
        }*/
        args = new String[]{"echo \"test\" | grep -i \"s\" " };
        try {
            String[] cmd = new String[3];
            Runtime rt = Runtime.getRuntime();
            System.out.println("Execing " + args[0]);
            //Change here: execute a shell with the command line instead of echo:
            Process proc = rt.exec(new String[]{"/bin/sh","-c", args[0]});
            // any error message?
            StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR");
            // any output?
            StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT");
            // kick them off
            errorGobbler.start();
            outputGobbler.start();
            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }

}

Sidenote.Для лучшего минимального теста:

  • Я заменил вашу команду mutt на grep, так как не хочу отправлять письма;)
  • Я подделал команду javaСтрока путем создания массива ("args") программно.

  • сделал ваш StreamGobbler статическим, чтобы он был одним файлом.

Все это не должно изменить ваш тестовый сценарий.Что действительно важно, так это вызов rt.exec, который выполняет оболочку вместо / bin / echo

пример выполнения:

Execing echo "test" | grep -i "s" 
ExitValue: 0
OUTPUT>test
...