Java远程执行Shell命令

1. Jar包:ganymed-ssh2-build210.jarweb

2. 步骤:算法

  a) 链接:bash

    Connection conn = new Connection(ipAddr);session

    conn.connect();app

  b)认证:ssh

    boolean authenticateVal = conn.authenticateWithPassword(userName, password);ide

     c) 打开一个Session: oop

    if(authenticateVal)ui

      Session session = conn.openSession();spa

  d) 执行Shell命令:

       1)如果执行简单的Shell命令:(如 jps 、last 这样的命令 )

        session.execCommand(cmd);

       2) 遇到问题:

          用方法execCommand执行Shell命令的时候,会遇到获取不全环境变量的问题,

          好比执行 hadoop fs -ls 可能会报找不到hadoop 命令的异常

          试着用execCommand执行打印环境变量信息的时候,输出的环境变量不完整

          与Linux主机创建链接的时候会默认读取环境变量等信息

          多是由于session刚刚创建尚未读取完默认信息的时候,execCommand就执行了Shell命令

        解决:

        因此换了另一种方式来执行Shell命令:

          // 创建虚拟终端

          session.requestPTY("bash");

          // 打开一个Shell

          session.startShell();

          // 准备输入命令

          PrintWriter out = new PrintWriter(session.getStdin());
                
                     // 输入待执行命令

          out.println(cmd);

          out.println("exit")

          // 6. 关闭输入流

          out.close();

            // 7. 等待,除非1.链接关闭;2.输出数据传送完毕;3.进程状态为退出;4.超时

          session.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 30000);       

        用这种方式执行Shell命令,会避免环境变量读取不全的问题,第7步里有许多标识能够用,好比当exit命令执行后或者超过了timeout时间,则session关闭                 

        这里须要注意,当一个Shell命令执行时间过长时,会遇到ssh链接超时的问题,

        解决办法:

          1. 以前经过把Linux主机的sshd_config的参数ClientAliveInterval设为60,同时将第7步中timeout时间设置很大,来保证命令执行完毕,

            由于是执行Mahout中一个聚类算法,耗时最少七、8分钟,数据量大的话,须要几个小时。

          2.  后来将命令改为了nohup的方式执行,nohup hadoop jar .... >> XXX.log && touch XXX.log.end &

            这种方式是提交到后台执行,即便当前链接断开也会继续执行,把命令的输出结果写入日志,若是hadoop命令执行成功,则生成.end文件

            获取文件的方法 ganymed-ssh2-build210.jar 也提供了,以下

              SCPClient scpClient = con.createSCPClient(); 

              scpClient.get("remoteFiles","localDirectory");  //从远程获取文件

   e) 获取Shell命令执行结果:

    InputStream stderr = new StreamGobbler(session.getStderr());

    InputStream in = new StreamGobbler(session.getStdout());

 1 private String processStdErr(InputStream in, String charset)
 2             throws IOException {
 3         BufferedReader br = new BufferedReader(new InputStreamReader(in, charset));
 4         StringBuffer sb = new StringBuffer();
 5         
 6         if (in.available() != 0) {
 7             while (true) {
 8                 String line = br.readLine();
 9                 if (line == null)
10                     break;
11                 sb.append(line).append(System.getProperty("line.separator"));
12             }
13         }
14         
15         return sb.toString();
16     }
获取流中数据
相关文章
相关标签/搜索