【问题标题】:Executing complex process commandline with java用java执行复杂的进程命令行
【发布时间】:2017-10-27 07:45:49
【问题描述】:

我尝试使用 ProcessBuilder 从 java 类执行命令行进程。
成功执行实际上会在我的 Eclipse 中打开另一个终端。
*就像:*
进程 ----> 打开 ----> 子进程
其余所有命令必须在子进程中执行

有人帮助我了解如何触发 子进程 并在完成后退出该子进程。

List commands = new ArrayList<String>();
    commands.add("mysql -u root -p ********");
    commands.add("select * from employee;");
    System.out.println(commands);
ProcessBuilder pb = new ProcessBuilder(commands);
Process process = pb.start();


注意:

给定的命令只是一个例子,问题与'jdbc'无关,都是关于进程和子进程的。

【问题讨论】:

  • 应该退出主进程,给我们看代码。
  • 用我试图执行的代码编辑,它只会启动主进程,如何在这个进程之上启动子进程。

标签: java linux command-line process


【解决方案1】:

您误解了如何调用操作系统进程。

每个进程都由程序名称(如notepad.exejava.exe)和零个或多个命令行参数组成。

ProcessBuilder 能够一次运行一个命令。构成其命令的字符串列表不是单独的命令;它们代表程序名称及其各个命令行参数。

因此,要运行 mysql,您需要将命令行参数分开:

ProcessBuilder pb = new ProcessBuilder("mysql", "-u", "root", "-p", password);

您的下一行select * from employee; 不是系统命令,也不是子进程。这是一个 mysql 命令——只有 mysql 才能理解的指令。您可能可以将其写入 mysql 进程的标准输入,因为 mysql 恰好通过标准输入接受命令:

try (Writer writer = new OutputStreamWriter(process.getOutputStream())) {
    write.write("select * from employee;");
}

然而,并非所有程序都通过其标准输入接受命令。

您似乎知道,mysql 不适合外部进程。读取和解析输出会比乍一看更困难。 JDBC 将是更好的选择。 (您似乎知道这一点,但我提到它是为了其他读者的利益。)

【讨论】:

  • 用外行的话很好地解释了,太好了。但是它看起来像类似的答案。需要的根本不是 myslq/jdbc。并且下一步涉及一个子过程,我无法比这个更好地解释它。所以这一切都假设查询是另一个子流程。具有挑战性的任务是解析输出并仅指出结果值。
  • 如何让外部进程产生自己的子进程完全取决于外部进程是什么。没有一种通用的方法可以让一个进程启动另一个进程。
【解决方案2】:

查看您的示例,您似乎正在尝试在 mysql 上运行 sql 命令。

首先,如果您真的想使用 msqyl 命令行命令执行此操作,您希望将其输入/输出重定向到 java InputStream/OutputStream,然后将您的 SQL 请求发送到 mysql 进程输入。您可能会遵循以下示例:

    List<String> command = new ArrayList<>();
    command.add("mysql -u root -p ********");
    ProcessBuilder pb = new ProcessBuilder(command);
    Process process = pb.start();
    PrintStream commandIn = new PrintStream(process.getOutputStream());
    commandIn.println("select * from employee;");

在 mysql 实例上运行 SQL 命令的第二个最佳方法是使用 JDBC 而不是 mysql 命令行工具。寻找大量的 JDBC 教程。

这是一个更完整(且有效)的示例。 看看这个“命令行工具”:

public class TestCmd {

    public static void main(String[] args) throws IOException
    {
        System.out.println("Started. args[0]=" + args[0]);

        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for(;;)
        {
            String line = in.readLine();
            if (line == null) break;
            System.out.println("echo:" + line);
        }
    }
}

然后“驱动程序”程序女巫演示了如何向这个命令行工具发送命令:

public class TestDriver {

    final static String JAVA_EXE = "C:\\...\\java.exe";
    final static String CLASS_BASEPATH = "C:\\...\\java\\bin";

    public static void main(String[] args) throws Exception
    {
        List<String> command = new ArrayList<>();
        command.add(JAVA_EXE.toString());
        command.add("-classpath");
        command.add(CLASS_BASEPATH);
        command.add("TestCmd");
        command.add("Parameter");
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.redirectOutput(new File("c:\\temp\\out.txt"));

        Process process = pb.start();
        PrintStream commandIn = new PrintStream(process.getOutputStream());

        commandIn.println("first input line");
        commandIn.flush();
        commandIn.println("second input line");
        commandIn.flush();

        // give some time to the sub process to finish writing its output
        Thread.sleep(100);

        process.destroy();
    }
}

在输出“out.txt”中你会得到,正如预期的那样:

Started. args[0]=Parameter
echo:first input line
echo:second input line

【讨论】:

  • 我明白你的意思,mysql 只是我在这里给出的一个示例,以便任何人都可以在命令行中执行它。我正在寻找一个没有任何 jdbc 类库的真正命令行脚本的执行。感谢伙伴的提示。我将编辑我的问题以反映观点。
  • 我为第一个解决方案添加了一个示例代码,可以满足您的需求。
  • 它根本不会触发 select * 查询..!
  • 我现在添加了一个完整的 java 工作示例。希望对你有帮助
  • 这是一个好主意,除了将其写入文件..我需要将结果作为字符串..干杯..!谢谢老哥
【解决方案3】:

我无法测试您正在执行的确切命令,但问题可能是它们实际上并没有停止执行,这就是您的主进程没有停止的原因。

解决方法是:

  1. 使用isAlive() 检查这些命令是否仍在执行(并在超时后终止这些进程)。
  2. 使用waitFor(long timeout, TimeUnit unit) 方法使它们在超时后终止。然后,您可以使用exitValue() 方法检查进程是否正常退出。

【讨论】:

  • 我已经用可执行命令更新了代码,这种情况会发生什么,因为“mysql”命令行会打开msql命令行子进程,那么我们必须执行select *查询..怎么办那个?
猜你喜欢
  • 2017-08-24
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
相关资源
最近更新 更多