如何在commons-exec下从Java中启动VI?

时间:2012-03-13 19:27:40

标签: java shell command vi

我希望能够从我的Java程序中启动VI并等待用户退出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重定向并没有成功。

之前有人必须这样做 - 帮助!

谢谢,

标记

3 个答案:

答案 0 :(得分:5)

但是,从Java 1.7开始,您可以使用下一个示例来透明地重定向并具有完整的控制台功能

A = ones(5,5,5);
B = zeros(size(A));
for i = 1 : size(A, 3)
    B(:,:,i) = conv2(A(:,:,i), ones(2), 'same');
end

这将允许您透明地为JVM 1.7 +打开VI。

答案 1 :(得分:2)

当Java通过Runtime.exec()运行程序时(这是commons-exec最终做的),它将程序的输入,输出和错误流作为输入/输出流连接到Java应用程序。这样的流肯定不是终端,你不能移动文本光标(因为它没有任何),更改文本颜色,或检测是否按下Shift键(因为它只是字节流而不是物理keyborad)。因此,像vi这样的交互式应用程序无法真正在终端等条件下运行。

顺便说一下,我不确定你提供的命令行args是由shell解析还是直接传递给程序。在后一种情况下,即使有一种方法让Java以某种方式允许程序用其他东西替换Java的连接流,你的/dev/tty重定向也无法工作。

顺便说一下,为什么你想从Java程序中运行vi似乎有点奇怪。

所以我想最好的解决方案是执行一个终端模拟器,如konsolegnome-terminalxterm,让它通过在命令行上传递相应的参数来运行vi(例如{{ 1}})。在这种情况下,终端的窗口应该弹出,konsole -e vi可以在其中运行。当然,如果你在无头服务器上它将无法工作,但无论如何运行vi都无济于事。

答案 2 :(得分:-1)

我不知道如何使用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

希望这有帮助。