2014-06-18 5 views
2

Java에서 SSH를 통해 원격 GNU/Linux 시스템에서 명령을 실행하는 데 문제가 있습니다. 다음 명령은 로컬 Bash에서 실행될 때 잘 동작합니다 (물론 사용자와 호스트는 다르지만 동작은 변경되지 않습니다).Java에서 SSH를 통해 Bash 명령을 실행할 때의 문제

$ ssh [email protected] 'hostname' 
host 
$ ssh [email protected] 'hostname -f' 
host.example.com 
$ ssh [email protected] "hostname -f" 
host.example.com 

것은 자바가 인수없이 hostname보다 더 복잡 아무것도 실패에서 내가 생각하는 것은 동일 하.

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import org.apache.commons.exec.CommandLine; 
import org.apache.commons.exec.DefaultExecutor; 
import org.apache.commons.exec.Executor; 
import org.apache.commons.exec.PumpStreamHandler; 

public class SOPlayground { 

    public static void main(String[] args) throws Exception { 
     for (String argument : new String[]{"hostname", "'hostname'", "\"hostname\"", 
      "'hostname -f'", "\"hostname -f\""}) { 
      CommandLine commandLine = new CommandLine("ssh"); 
      commandLine.addArgument("[email protected]"); 
      commandLine.addArgument(argument); 
      System.out.println(commandLine); 

      final Executor executor = new DefaultExecutor(); 

      try (ByteArrayOutputStream os = new ByteArrayOutputStream(); 
        ByteArrayOutputStream err = new ByteArrayOutputStream()) { 
       executor.setStreamHandler(new PumpStreamHandler(os, err)); 
       int exitcode = executor.execute(commandLine); 
       System.out.println("exitcode=" + exitcode); 
       System.out.println(new String(os.toByteArray(), "UTF-8")); 
       System.err.println(new String(err.toByteArray(), "UTF-8")); 
      } catch (IOException ex) { 
       System.err.println(ex.getMessage()); 
      } 
     } 
    } 
} 

출력은 다음과 같습니다

ssh [email protected] hostname 
exitcode=0 

host 

ssh [email protected] 'hostname' 
exitcode=0 

host 

ssh [email protected] "hostname" 
exitcode=0 
host 


ssh [email protected] 'hostname -f' 
Process exited with an error: 127 (Exit value: 127) 
ssh [email protected] "hostname -f" 
Process exited with an error: 127 (Exit value: 127) 

당신이 볼 수 있듯이, 자바에서 SSH를 통해 hostname -f을 실행 내가 무엇 배쉬 (로컬 또는 원격)이 없습니다 궁금해 127 종료 코드로 실패 무엇을 찾으십니까? 명령.

나는 변형

addArgument(String argument, boolean handleQuoting) 

을 사용하려했지만 결과의 차이는 없었다.

SSH를 통해 작동하는 Java에서 CommandLine을 어떻게 작성해야합니까?

+2

는 jsch (com.jcraft.jsch.JSch)을 사용해보십시오 - 그것은 내가 다른 접근 방식에 JSch을 시도했지만 공개 키 인증을 구성하는 데 실패했습니다 ssh를 –

+0

위한 목적으로 제작되었습니다. 그것에 관한 어떤 암시라도? –

+0

미안 해요 'JSch shell = new JSch();와 같이 username/passwd와 함께 사용했습니다. \t \t session = shell.getSession (userName, serverIP, 22); \t \t session.setPassword (password); ' –

답변

2

공개 키 인증과 함께 JSch를 사용할 수 있습니다.

당신은 단지 하나의 원격 명령을 실행 exec를 사용하려면 다음 여기에, 연결을 닫습니다 경우 작업 예제를 가지고 :

public static void main(String[] args) { 

     String user = "--"; 
     String host = "--"; 

     try 
     { 
      JSch jsch = new JSch(); 
      // key authentication 
      jsch.addIdentity("id_rsa"); 
      // open a new session on port 22 
      Session session = jsch.getSession(user, host, 22); 
      session.setConfig("StrictHostKeyChecking", "no"); 

      session.connect(); 
      String command = "ls /"; 
      Channel channel = session.openChannel("exec"); 
      ((ChannelExec) channel).setCommand(command); 

      channel.setInputStream(null); 

      ((ChannelExec) channel).setErrStream(System.err); 

      InputStream in = channel.getInputStream(); 

      channel.connect(); 
      StringBuilder sb = new StringBuilder(); 
      byte[] tmp = new byte[1024]; 
      while (true) 
      { 
       while (in.available() > 0) 
       { 
        int i = in.read(tmp, 0, 1024); 
        if (i < 0) 
         break; 
        sb.append(new String(tmp, 0, i)); 
       } 
       if (channel.isClosed()) 
       { 
        if (in.available() > 0) 
         continue; 
        System.out.println("exit-status: " 
          + channel.getExitStatus()); 
        break; 
       } 
       try 
       { 
        Thread.sleep(500); 
       } 
       catch (Exception ee) 
       { 
       } 
      } 
      //disconnecting and closing 
      channel.disconnect(); 

      session.disconnect(); 
      System.out.println("Output: "); 
      System.out.println(sb.toString()); 
     } 
     catch (Exception e) 
     { 
      //something should be done here 
      e.printStackTrace(); 

     } 
    } 

출력 :

exit-status: 0 
Output: 
1 
bin 
boot 
cgroup 
dev 
etc 
home 
lib 
lib64 
lost+found 
.... 

이 희망 그것이

을하는 데 도움이

참고 : id_rsa은 키 파일의 경로입니다

0

Jsch에 대한 답변 주셔서 감사합니다. 임시 파일에 명령을 쓰고 로컬로 실행하는 다른 방법을 시도했습니다.

import java.io.ByteArrayOutputStream; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import org.apache.commons.exec.CommandLine; 
import org.apache.commons.exec.DefaultExecutor; 
import org.apache.commons.exec.Executor; 
import org.apache.commons.exec.PumpStreamHandler; 
import org.apache.commons.io.IOUtils; 

public class SOPlayground { 

    public static void main(String[] args) throws Exception { 
     final String command = "ssh [email protected] 'hostname -f'"; 
     int exitCode = executeCommand(command); 
    } 

    private static int executeCommand(final String command) { 
     int exitcode = -1; 
     File temp = null; 
     try { 
      temp = File.createTempFile("foo", ".tmp"); 
      try (OutputStream os = new FileOutputStream(temp);) { 
       IOUtils.write(command, os); 
      } finally { 
       // os is closed 
      } 

      CommandLine commandLine = new CommandLine("bash"); 
      commandLine.addArgument(temp.getAbsolutePath()); 

      final Executor executor = new DefaultExecutor(); 
      try (ByteArrayOutputStream os = new ByteArrayOutputStream(); 
        ByteArrayOutputStream err = new ByteArrayOutputStream()) { 
       executor.setStreamHandler(new PumpStreamHandler(os, err)); 
       exitcode = executor.execute(commandLine); 
       System.out.println("exitcode=" + exitcode); 
       System.out.println(new String(os.toByteArray(), "UTF-8")); 
       System.err.println(new String(err.toByteArray(), "UTF-8")); 
      } finally { 
       // os and err are closed 
      } 
     } catch (IOException ex) { 
      System.err.println(ex.getMessage); 
     } finally { 
      if (temp != null) { 
       temp.delete(); 
      } 
     } 
     return exitcode; 
    } 
} 
관련 문제