Java SSH远程执行Shell脚本实现,以及此过程中bash: xx: command not found解决方案

首先我们需要先引入依赖

Jar包:ganymed-ssh2-build210.jar

	  <dependency>
            <groupId>ch.ethz.ganymed</groupId>
            <artifactId>ganymed-ssh2</artifactId>
            <version>build210</version>
      </dependency>

因为我们可能需要用到这里的一些类

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

话不多说,上代码

 public static void main(String[] args) throws Exception {
     		//需要执行的命令
          String command = "cat log.txt";
          //host
          String host="dcmaster02";
          Connection conn= new Connection(host);
          Session ssh = null;
          conn.connect();
          String username="hadoop";
          String password="hadoop";
          boolean isconn=conn.authenticateWithPassword(username, password);
          if(!isconn){
              System.out.println("用户名称或者是密码不正确");
          }else{
              System.out.println("已经连接OK");
              ssh=conn.openSession();
              //执行
              ssh.execCommand(command);
              //返回正确输出
              InputStream stdout = new StreamGobbler(ssh.getStdout());
              //返回错误输出
              InputStream stderr = new StreamGobbler(ssh.getStderr());
              BufferedReader stdoutReader = new BufferedReader(
                      new InputStreamReader(stdout));
              BufferedReader stderrReader = new BufferedReader(
                      new InputStreamReader(stderr));
              System.out.println("Here is the output from stdout:");
              while (true) {
                  String line = stdoutReader.readLine();
                  if (line == null)
                      break;
                  System.out.println(line);
              }
              System.out.println("Here is the output from stderr:");
              while (true) {
                  String line = stderrReader.readLine();
                  if (line == null)
                      break;
                  System.out.println(line);
              }
          }
          ssh.close();
          conn.close();
      }

这样就可以执行成功了,但若是执行简单的Shell命令:(如 jps 、last 这样的命令 ),一般不会出问题

  ssh.execCommand(command);

重点:遇到问题:
用方法execCommand执行Shell命令的时候,会遇到获取不全环境变量的问题,比如执行 hadoop fs -ls 可能会报找不到hadoop 命令的异常,试着用execCommand执行打印环境变量信息的时候,输出的环境变量不完整与Linux主机建立连接的时候会默认读取环境变量等信息,可能是因为session刚刚建立还没有读取完默认信息的时候,execCommand就执行了Shell命令
例如我执行

String command="yarn application -kill application_1597932203385_0571";
ssh.execCommand(command);

打印结果

已经连接OK
Here is the output from stdout:
Here is the output from stderr:
bash: yarn: command not found

bash: yarn: command not found,就是因为session刚刚建立还没有读取完默认信息的时候,execCommand就执行了Shell命令

解决办法:
换另外一种方式来执行Shell命令:

	// 建立虚拟终端
      ssh.requestPTY("bash");
     // 打开一个Shell
      ssh.startShell();
       // 准备输入命令
      PrintWriter out = new PrintWriter(ssh.getStdin());
      // 输入待执行命令
      out.println(command);
      out.println("exit");
        // 关闭输入流
      out.close();
   //  等待,除非1.连接关闭;2.输出数据传送完毕;3.进程状态为退出;4.超时
      ssh.waitForCondition(ChannelCondition.CLOSED | ChannelCondition.EOF | ChannelCondition.EXIT_STATUS , 10000);
               

用这种方式执行Shell命令,会避免环境变量读取不全的问题,第7步里有许多标识可以用,比如当exit命令执行后或者超过了timeout时间,则session关闭 ,这里需要注意,当一个Shell命令执行时间过长时,会遇到ssh连接超时的问题,可以将Linux主机的sshd_config的参数ClientAliveInterval设为60,同时将第最后一步中timeout时间设置很大,来保证命令执行完毕

你可能感兴趣的:(java,linux,shell,大数据)