2012-03-13 4 views
2

Java 프로그램 내에서 VI를 시작하고 계속하기 전에 VI를 종료 할 때까지 기다리고 싶습니다. 여기에 내가 현재 가지고있는 코드는 다음과 같습니다commons-exec에서 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에서 리디렉션하는 것이 트릭을 수행하지 않습니다.

누군가 도움이 필요합니다.

감사합니다,

마크

나는 평민 - 간부와 함께 할 방법을 잘 모르겠어요

답변

-1

,

그러나 표준 자바의 라인을 따라 뭔가해야 ...

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

잘하면이 도움이됩니다.

+0

vi가 포 그라운드로 가져 오지 않고 사용자의 tty에 연결되어 있기 때문에 (이 질문은 실제로 무엇을 묻고 있는지 분명하게 알 수 있습니다) 작동하지 않습니다. –

3

Java가 Runtime.exec()을 통해 프로그램을 실행하면 (이것은 commons-exec가 결국 수행하는 것입니다.) 프로그램의 입력, 출력 및 오류 스트림을 입/출력 스트림으로 Java 응용 프로그램에 연결합니다. 이러한 스트림은 분명히 터미널이 아니며, 예를 들어 텍스트 커서를 이동 (문자가 없기 때문에)하거나, 텍스트 색상을 변경하거나, Shift 키가 눌려 졌는지 감지 할 수는 없습니다 (단지 바이트 스트림이기 때문에). 물리적 인 키보드는 아닙니다). 따라서 vi과 같은 대화식 앱은 터미널과 같은 조건에서 실제로 작동 할 수 없습니다.

덧붙여서, 커멘드 라인이 당신이 제공하는 인수가 쉘에 의해 해석되는지, 프로그램에 직접 건네 졌는지는 모르겠습니다. 후자의 경우 /dev/tty으로 리다이렉션하는 것은 자바가 어떻게 든 프로그램이 자바의 연결된 스트림을 다른 것으로 대체하도록 허용하는 방법이 있었다고해도 작동하지 않을 수 있습니다.

이외에도 Java 프로그램 내부에서 vi을 실행하려는 이유가 약간 이상하게 보입니다.

그래서 나는 최선의 해결책이 konsole 또는 gnome-terminal 또는 xterm 같은 터미널 에뮬레이터를 실행하고 그것의 명령 행 (예를 들어, konsole -e vi)에 해당하는 인수를 전달하여 VI를 실행할 수 있도록하는 것 같다. 이 경우 단말기의 창이 열리고 내부에서 vi이 작동 할 수 있습니다. 물론 헤드리스 서버를 사용하는 경우에는 작동하지 않지만 vi을 실행하면 어쨌든 유용하지 않습니다.

+0

서브 프로세스의'OutputStream' (서브 프로세스의 stdin)에'System.in'을 펌핑하는 것과 같은 것들을 시도해 보았습니다. 기본적으로 작동하지 않습니다. 슬픈, 이것이 내가 정말로하고 싶은 일인 것처럼. –

+0

@ChristopherSchultz 불행히도 입력을 생성하고 출력을 소비해야합니다. 그렇지 않으면 풀 버퍼로 인해 프로세스가 멈출 수 있습니다. –

+0

예, 모든 스트림을 펌프해야한다는 것을 알고 있습니다. 여전히 간단하게 작동하지 않습니다. 나는 자바에서 그것을 포기했다. 다행스럽게도 C에서 수행하는 것은 fork + exec와 같이 간단합니다. 나는 대부분 JNI가 번거롭게 할 가치가 없기 때문에 JNI가 포크 + 임무를 수행하도록 쓰기 위해 노력하지 않았다. –

2

그러나 Java 1부터.7 투명 이것은 당신이 JVM을 위해 1.7+ 투명하게 VI를 열 수 있습니다

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"); 

전체 콘솔 기능을 리디렉션하도록 다음 예제를 사용할 수 있습니다.

관련 문제