从Java Runtime.getRuntime执行linux mutt不发送邮件也不给出erorr

时间:2019-03-04 11:50:21

标签: java linux runtime mutt

我尝试在Linux和Java中使用Mutt发送电子邮件 如果我从linux命令行执行mutt命令,电子邮件将发送

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 :(得分:1)

您不会出错,因为echo似乎在您的系统上可用(通常为“ / bin / echo”)。运行时exec方法中的Stringtokenizer会将行的其余部分作为参数传递给/ bin / echo,如下所示:

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

这是一个有效的命令,因为它调用/ bin / echo并且/ bin / echo输出所有参数,但从不调用mutt。 (顺便说一句,/ bin / echo与内置的Bash shell中使用的回声是不同的,其行为略有不同...)

有时,它们(Java)对exec方法中的命令进行标记化可能很方便,但会导致类似这样的令人不快的效果,因为它使人认为某些事情应该起作用,但实际上在这种情况下不起作用... < / p>

您可能想要的是执行命令行的shell。因此,您必须实际执行一个shell(我在文件中标记了更改):

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();
        }
    }

}

侧注。为了获得更好的最小测试用例:

  • 我用一些grep替换了您的mutt命令,因为我不想发送邮件;)
  • 我通过以编程方式创建array(“ args”)伪造了Java命令行。

  • 将您的StreamGobbler设为静态,以使其只有一个文件。

所有这些都不会改变您的测试用例。有所不同的是执行外壳程序而不是/ bin / echo

的rt.exec调用

示例运行:

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