【原】Java程序调用远程Shell脚本

此程序的目的是执行远程机器上的Shell脚本。

【环境参数】
远程机器IP:192.168.234.123
用户名:root
密码:root
Shell脚本的路径:/home/IFileGenTool/BakProvisionAndOccurEntrance.sh

【具体步骤】
1、在远程机器上,准备Shell脚本。
[root@localhost IFileGenTool]# vim ./load_data.sh

1 #!/bin/sh
2 source /etc/profile
3 dbName=$1
4 tableName=$2
5 echo [`date +'%Y-%m-%d %H:%M:%S'`]' start loading data...'
6 mysql -uroot -p123456 -P3306 ${dbName} -e "LOAD DATA LOCAL INFILE '/home/IFileGenTool/bak_data/bak_data_bak.txt' INTO TABLE ${tableName} FIELDS TERMINATED BY ';'"
7 echo [`date +'%Y-%m-%d %H:%M:%S'`]' end loading data...'
8 exit
9 EOF

2、导入需要依赖的jar包。
Java远程调用Shell脚本这个程序需要ganymed-ssh2-build210.jar包。
下载地址:http://www.ganymed.ethz.ch/ssh2/
为了调试方便,可以将ganymed-ssh2-build210src下的代码直接拷贝到我们的工程里,
此源码的好处就是没有依赖很多其他的包,拷贝过来干干净净。

1 <dependency>
2     <groupId>org.jvnet.hudson</groupId>
3     <artifactId>ganymed-ssh2</artifactId>
4     <version>build210-hudson-1</version>
5 </dependency>


3、编写RemoteShellExecutor工具类。

  1 import java.io.IOException;
  2 import java.io.InputStream;
  3 import java.io.UnsupportedEncodingException;
  4 import java.nio.charset.Charset;
  5 
  6 import org.apache.commons.io.IOUtils;
  7 
  8 import ch.ethz.ssh2.ChannelCondition;
  9 import ch.ethz.ssh2.Connection;
 10 import ch.ethz.ssh2.Session;
 11 import ch.ethz.ssh2.StreamGobbler;
 12 
 13 public class RemoteShellExecutor {
 14      
 15      private Connection conn;
 16      /** 远程机器IP */
 17      private String ip;
 18      /** 用户名 */
 19      private String osUsername;
 20      /** 密码 */
 21      private String password;
 22      private String charset = Charset.defaultCharset().toString();
 23 
 24      private static final int TIME_OUT = 1000 * 5 * 60;
 25 
 26      /**
 27       * 构造函数
 28       * @param ip
 29       * @param usr
 30       * @param pasword
 31       */
 32      public RemoteShellExecutor(String ip, String usr, String pasword) {
 33           this.ip = ip;
 34          this.osUsername = usr;
 35          this.password = pasword;
 36      }
 37 
 38 
 39      /**
 40      * 登录
 41      * @return
 42      * @throws IOException
 43      */
 44      private boolean login() throws IOException {
 45          conn = new Connection(ip);
 46          conn.connect();
 47          return conn.authenticateWithPassword(osUsername, password);
 48      }
 49 
 50      /**
 51      * 执行脚本
 52      * 
 53      * @param cmds
 54      * @return
 55      * @throws Exception
 56      */
 57      public int exec(String cmds) throws Exception {
 58          InputStream stdOut = null;
 59          InputStream stdErr = null;
 60          String outStr = "";
 61          String outErr = "";
 62          int ret = -1;
 63          try {
 64          if (login()) {
 65              // Open a new {@link Session} on this connection
 66              Session session = conn.openSession();
 67              // Execute a command on the remote machine.
 68              session.execCommand(cmds);
 69              
 70              stdOut = new StreamGobbler(session.getStdout());
 71              outStr = processStream(stdOut, charset);
 72              
 73              stdErr = new StreamGobbler(session.getStderr());
 74              outErr = processStream(stdErr, charset);
 75              
 76              session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT);
 77              
 78              System.out.println("outStr=" + outStr);
 79              System.out.println("outErr=" + outErr);
 80              
 81              ret = session.getExitStatus();
 82          } else {
 83              throw new Exception("登录远程机器失败" + ip); // 自定义异常类 实现略
 84          }
 85          } finally {
 86              if (conn != null) {
 87                  conn.close();
 88              }
 89              IOUtils.closeQuietly(stdOut);
 90              IOUtils.closeQuietly(stdErr);
 91          }
 92          return ret;
 93      }
 94 
 95      /**
 96      * @param in
 97      * @param charset
 98      * @return
 99      * @throws IOException
100      * @throws UnsupportedEncodingException
101      */
102      private String processStream(InputStream in, String charset) throws Exception {
103          byte[] buf = new byte[1024];
104          StringBuilder sb = new StringBuilder();
105          while (in.read(buf) != -1) {
106              sb.append(new String(buf, charset));
107          }
108          return sb.toString();
109      }
110 
111     public static void main(String args[]) throws Exception {
112         RemoteShellExecutor executor = new RemoteShellExecutor("192.168.234.123", "root", "beebank");
113         // 执行myTest.sh 参数为java Know dummy
114         System.out.println(executor.exec("/home/IFileGenTool /load_data.sh t_users myDataBase01"));
115     }
116 }

4、Java程序调用远程Shell

private void backupAndRestoreData(String originalTableName) throws Exception {
    
    //1. 调用远程Shell脚本,对生产库中数据进行导出和导入备份。                
    LogUtil.getLogger().info("######    1. 开始对数据库中数据利用进行导出和导入备份   ######");
    RemoteShellExecutor executor = new RemoteShellExecutor("192.168.234.123", "root", "root");
    // 执行myTest.sh 参数为java Know dummy
    System.out.println(executor.exec("/home/IFileGenTool/load_data.sh"));
}

5、运行结果

备份数据成功。

6、说明:
0 // getExitStatus方法的返回值

注:一般情况下shell脚本正常执行完毕,getExitStatus方法返回0。
此方法通过远程命令取得Exit Code/status。但并不是每个server设计时都会返回这个值,如果没有则会返回null。
在调用getExitStatus时,要先调用WaitForCondition方法,通过ChannelCondition.java接口的定义可以看到每个条件的具体含义。见以下代码:
ChannelCondition.java的源代码

参考连接:http://yu.you163.blog.163.com/blog/static/339877742012117101039968/

原文地址:https://www.cnblogs.com/zjrodger/p/5551385.html