Как я могу запустить VI из Java под commons-exec? - PullRequest
4 голосов
/ 13 марта 2012

Я хотел бы иметь возможность запускать VI из моей Java-программы и ждать, пока пользователь не закроет VI, прежде чем продолжить. Вот фрагмент кода, который у меня есть на данный момент:

...    
String previewFileName="test.txt"; // the file to edit
CommandLine cmdLine = new CommandLine("/usr/bin/vi");
cmdLine.addArgument(previewFileName);
cmdLine.addArgument(">/dev/tty");
cmdLine.addArgument("</dev/tty");

Executor executor = new DefaultExecutor();
try
{
    DefaultExecuteResultHandler resultHandler = new ResetProcessResultHandler(cmdLine);
    executor.execute(cmdLine, resultHandler);
} catch (IOException e)
{
    throw new Error("Cannot execute command: /usr/bin/vi " + previewFileName, e);
}
log.info("waiting...");
cmdLine.wait();
log.info("...done");
...

private class ResetProcessResultHandler extends DefaultExecuteResultHandler
{
    private final CommandLine mCommandLine;
    public ResetProcessResultHandler(CommandLine pCommandLine)
    {
        mCommandLine = pCommandLine;
    }
    public void onProcessComplete(int exitValue)
    {
        log.info("Command complete  rc(" + exitValue + ")");
        if (exitValue != 0)
        {
            throw new RuntimeException("VI command error [rc=" + exitValue + "] " );
        }
        mCommandLine.notify();
    }
    public void onProcessFailed(ExecuteException e)
    {
        if (e.getExitValue() != 0)
        {
            log.error("launch VI error " + e.toString());
            throw new RuntimeException("VI command failed [" + e.getCause() + "] ");
        }
        else
        {
            log.info("VI complete   rc(" + e.getExitValue() + ")");
        }
        mCommandLine.notify();
    }
}

Я получаю вывод:

Vim:  output is not to a terminal
Vim:  input is not from a terminal

Но потом я вижу экран, нарисованный так, как будто VI запустился; и VI не читает символы, которые я печатаю.

Так что ... перенаправление из / dev / tty не помогает.

Кто-то должен был сделать это раньше - помогите!

Спасибо

Mark

Ответы [ 3 ]

5 голосов
/ 30 апреля 2015

Однако, начиная с Java 1.7, вы можете использовать следующий пример для прозрачного перенаправления и полной функциональности консоли

System.out.println("STARTING VI");
 ProcessBuilder processBuilder = new ProcessBuilder("/usr/bin/vi");
 processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
 processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
 processBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT);

 Process p = processBuilder.start();
  // wait for termination.
  p.waitFor();
System.out.println("Exiting VI");

Это позволит вам прозрачно открыть VI для JVM 1.7 +.

2 голосов
/ 13 марта 2012

Когда Java запускает программу через Runtime.exec() (и это в конце концов делает commons-exec), она соединяет потоки ввода, вывода и ошибок программы с вашим Java-приложением как потоки ввода-вывода. Такой поток, конечно, не является терминалом, например, вы не можете переместить текстовый курсор в нем (поскольку он не имеет никакого), изменить цвета текста или определить, нажата ли клавиша Shift (так как это просто поток байтов а не физического кейборада). Таким образом, интерактивное приложение, такое как vi, не может работать в таких условиях, как в терминале.

Кстати, я не уверен, что введенные вами аргументы командной строки анализируются оболочкой или передаются непосредственно в программу. В последнем случае ваше перенаправление на /dev/tty может не сработать, даже если бы у Java был способ каким-то образом позволить программе заменить подключенные потоки Java чем-то другим.

Кроме того, кажется странным, почему вы хотите запустить vi изнутри Java-программы.

Так что я думаю, что лучшее решение - запустить эмулятор терминала, такой как konsole или gnome-terminal или xterm, и позволить ему запустить vi, передав соответствующий аргумент в его командной строке (например, konsole -e vi). В этом случае должно появиться окно терминала, и vi может функционировать внутри него. Конечно, это не сработает, если вы работаете на автономном сервере, но тогда запуск vi не может быть полезен в любом случае.

0 голосов
/ 13 марта 2012

Я не уверен, как это сделать с помощью commons-exec,

Но стандартная Java должна быть чем-то вроде ...

String[] command = {"/usr/bin/vi", "test.txt"};
Process vimProcess = Runtime.getRuntime().exec(command);
vimProcess.waitFor();

Это заставит текущий поток ждать завершения процесса. Вы также можете использовать vimProcess.getInputStream (), getOutputStream () и getErrorStream (), чтобы перенаправить их в файлы журналов или куда бы вы ни захотели.

Смотрите здесь для более подробной информации. http://docs.oracle.com/javase/6/docs/api/java/lang/Runtime.html

Надеюсь, это поможет.

...