如何以正确的方式多次运行java的bash脚本?

时间:2015-02-02 18:00:53

标签: java multithreading bash

不需要说我是JAVA的新手。

我写了一个JAVA应用程序,用户可以在Linux机器上运行脚本并可以多次运行它。 (脚本需要时间(10-20分钟)来完成它的工作)。

问题是,当我多次运行此脚本时,应用程序变得非常慢,甚至冻结了一小时才能完成它的工作。

我使用多线程来完成这项任务。但我想我把它放错了地方。如何解决这个问题?

代码很大,有几个类可以把它放在这里。我只是把相关的代码。

public static String executeWithTrace(String command, JTextArea output) {
    StringBuilder sb = new StringBuilder();

    String[] commands = new String[]{"/bin/bash", "-c", command};
    try {
        Process proc = new ProcessBuilder(commands).start();
        BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(proc.getInputStream()));

        BufferedReader stdError = new BufferedReader(new
                InputStreamReader(proc.getErrorStream()));

        String s = null;
        while ((s = stdInput.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
            output.setText(output.getText()+"\n"+s);
            output.setCaretPosition(output.getText().length());
            System.out.println(s);
        }

        while ((s = stdError.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
            output.setText(output.getText()+"\n"+s);
            output.setCaretPosition(output.getText().length());
            System.out.println(s);
        }
    } catch (IOException e) {
        return e.getMessage();
    }
    System.out.println(sb.toString());
    return sb.toString();
}

这是executeWithTrace方法调用的地方:

public void runMethod(final String ip) {

    progressBar.setIndeterminate(true);
    ruSTB1 = new Runnable() {
        public void run() {
            input.setText(ip);


            if (Shell.methodssh( "rm -rf /afile " ,input,output) == null) {

                password=passwordMethod();

                Bash.executeWithTrace("bashScript.sh",output);



                }

            else {
                output.setText("Error \n Check IP address ");
                thrSTB1.interrupt();
            }
            SwingUtilities
            .invokeLater(new Runnable() {
                // @Override
                public void run() {
                    progressBar
                            .setIndeterminate(false);
                }
            });

        }
    };
    thrSTB1 = new Thread(ruSTB1);
    thrSTB1.start();

}

1 个答案:

答案 0 :(得分:0)

executeWithTrace方法按顺序读取stdoutstderr的所有输出(首先stdout然后stderr)。

Process课程的文档说:

  

父进程使用这些流向子进程提供输入并从子进程获取输出。由于某些本机平台仅为标准输入和输出流提供有限的缓冲区大小,因此无法及时写入输入流或读取子进程的输出流可能导致子进程阻塞甚至死锁。

所以你的实现可能会阻止。必须同时阅读proc.getInputStream()proc.getErrorStream()

可能看起来像(可能你必须调整异常处理):

public static String executeWithTrace(String command, JTextArea output) {
final StringBuilder sb = new StringBuilder();

String[] commands = new String[]{"/bin/bash", "-c", command};
try {
    final Process proc = new ProcessBuilder(commands).start();

    new Thread() {
       @Override
       public void run() {

          BufferedReader stdInput = new BufferedReader(new
            InputStreamReader(proc.getInputStream()));
          String s = null;

          while ((s = stdInput.readLine()) != null) {
              sb.append(s);
              sb.append("\n");

              final fLine = s;
              // update the text area in the EDT
              SwingUtilities.invokeLater(new Runnable() {
                 @Override
                 public void run() {
                      output.setText(output.getText()+"\n"+fLine );
                      output.setCaretPosition(output.getText().length());
                      System.out.println(fLine);
                 }
              }
          }
      }
    }.start();


    new Thread() {
       @Override
       public void run() {
          BufferedReader stdError = new BufferedReader(new
                  InputStreamReader(proc.getErrorStream()));
          while ((s = stdError.readLine()) != null) {
              sb.append(s);
              sb.append("\n");

              final fLine = s;
              // update the text area in the EDT
              SwingUtilities.invokeLater(new Runnable() {
                 @Override
                 public void run() {
                     output.setText(output.getText()+"\n"+s);
                     output.setCaretPosition(output.getText().length());
                     System.out.println(s);
                 }
              }
          }
      }
    }.start();

    proc.waitFor();
} catch (IOException e) {
    return e.getMessage();
}
System.out.println(sb.toString());
return sb.toString();
}