java 新进程(ProcessBuilder) 远程(Ganymed SSH-2)

转载自: http://www.youzitool.com/index/detail/id/23.html

我们在日常开发中,有时候会遇到触发一个linux命令,比如清理临时文件,或者触发一个shell命令。那么这个时候就需要通过java去调用shell命令。 这里我们使用java自带的ProcessBuilder 来完成任务。ProcessBuilder类是用于创建操作系统进程.

//其中List<String> orders 就是待执行的命令
//比如 orders.add("hadoop")
// orders.add("fs")
// orders.add("-ls")
// orders.add("filePath+fileName")

public static List<String> execute(List<String> orders)
            throws IOException, InterruptedException {
        List<String> sb = new ArrayList<String>();

        Process p = null;
        InputStream is = null;
        BufferedReader br = null;

        try {
            //构造ProcessBuilder,并将需要执行的命令传入
            ProcessBuilder pb = new ProcessBuilder(orders);
            //启动进程,并获取输出流
            p = pb.redirectErrorStream(true).start();

            is = p.getInputStream();
            br = new BufferedReader(new InputStreamReader(is));
            String line;
            while ((line = br.readLine()) != null) {
                sb.add(line);
                LoggerUtil.error("util", "info", line);
            }
            //等待进程
            p.waitFor();

            return sb;
        } finally {
            if (p != null) {
                close(p.getOutputStream());
                close(p.getInputStream());
                close(p.getErrorStream());
                p.destroy();
            }
            if (br != null) {
                br.close();
            }
            if (is != null) {
                is.close();
            }
        }
    }

    private static void close(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
            }
        }
    }
}


这样就能够通过hadoop 获取文件大小。但这里会有一个隐藏的坑。那就是ProcessBuilder 的环境变量问题
如果你没有在脚本里指明hadoop 依赖的环境变量路径,那么执行就会报错,所以我们需要依赖系统的环境变量,只需要在 pb  = new ProcessBuilder 对象之后,pb.environment(); 就可以获取到系统默认的环境变量。

通过上面的方式就能够执行本地shell命令,这时候可能又会有另外一个需求,通过本机远程ssh到另外一台机器上去执行shell命令,这种使用方式经常用于一台机器集群管理其他机器的需求。

这里我们使用 Ganymed SSH-2 for Java http://www.ganymed.ethz.ch/ssh2/

Ganymed SSH-2 for Java is a library which implements the SSH-2 protocol in pure Java (tested on J2SE 1.4.2 and 5.0). It allows one to connect to SSH servers from within Java programs. It supports SSH sessions (remote command execution and shell access), local and remote port forwarding, local stream forwarding, X11 forwarding, SCP and SFTP. There are no dependencies on any JCE provider, as all crypto functionality is included.


Ganymed SSH-2 for Java是用纯Java实现SSH-2协议的一个包。可以利用它直接在Java程序中连接SSH服务器。Ganymed SSH-2支持SSH对话(远程命令执行和shell访问),本地和远程端口转发,本地数据流转发,X11转发和SCP。这些都没有依赖任何JCE provider,而且所有这些都包含加密的功能。

//cmd 是待执行的shell命令.
//logFile 执行过程中,记录返回日志的文件
  public ShellResult<String> execute(String cmd, String logFile){
        if(StringUtils.isBlank(cmd)){
            return new ShellResult<String>("cmd_is_null");
        }
        if(StringUtils.isBlank(logFile)){
            return new ShellResult<String>("logFile_is_null");
        }
        ShellResult<String> result = new ShellResult<String>("no_exec");
        InputStream stdOut;
        InputStream stdErr;
        try{
            if(login()){
                //打开一个会话
                Session session = conn.openSession();
                //执行远程命令
                session.execCommand(cmd);
                stdOut = new StreamGobbler(session.getStdout());
                stdErr = new StreamGobbler(session.getStderr());

                BufferedReader stdOutRead = new BufferedReader(new InputStreamReader(stdOut));
                String line = stdOutRead.readLine();
                while (line != null){
                    LoggerUtil.error(logFile, "INFO", line);
                    line = stdOutRead.readLine();
                }
                BufferedReader stdErrRead = new BufferedReader(new InputStreamReader(stdErr));
                line = stdErrRead.readLine();
                while (line != null){
                    LoggerUtil.error(logFile, "Exception", line);
                    line = stdOutRead.readLine();
                }
               //这里要等待会话结束返回
                session.waitForCondition(ChannelCondition.EXIT_STATUS, Long.MAX_VALUE);
                //根据会话返回结果判断执行是否成功
                int ret = session.getExitStatus();
                if(ret == 0){
                    result.setSuccess(true);
                }else{
                    result.setErrorMsg("exec_error,ret="+ret);
                }
                session.close();
            }
        }catch (Exception e){
            result.setErrorMsg(e.getMessage());
        }finally {
            conn.close();
        }
        return result;
    }
    private boolean login() throws IOException{
        //连接ip地址
        conn = new Connection("127.0.0.1");
        conn.connect();
        //等待返回,连接成功则返回true,第一个参数为用户名,第二个参数为密码
        return conn.authenticateWithPassword("user","password");
    }




可以使用JavaProcessBuilder类来远程调用shell脚本。ProcessBuilder类允许您启动并控制外部进程。以下是一个示例代码,它使用ProcessBuilder类从远程服务器上运行shell脚本。 ``` import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class RemoteShellExecutor { public static void main(String[] args) throws IOException, InterruptedException { String host = "remote-host"; // 远程服务器IP地址或域名 String user = "remote-user"; // 远程服务器用户名 String password = "remote-password"; // 远程服务器密码 String command = "/path/to/remote/script.sh"; // 远程服务器上的shell脚本路径 // 创建ProcessBuilder对象 ProcessBuilder processBuilder = new ProcessBuilder(); // 设置远程SSH连接命令 processBuilder.command("sshpass", "-p", password, "ssh", user + "@" + host, command); // 启动进程 Process process = processBuilder.start(); // 读取进程输出 BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } // 等待进程结束 int exitCode = process.waitFor(); System.out.println("Process exited with code " + exitCode); } } ``` 在上面的示例代码中,我们使用ProcessBuilder类创建了一个SSH连接命令,并将其设置为要执行的命令。然后,我们启动进程,并使用一个缓冲读取器来读取进程输出。最后,我们等待进程结束,并打印进程退出代码。请注意,您需要在本地计算机上安装sshpass软件包,以便使用密码连接到远程服务器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值