/** * Copyright 2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.sf.katta.tool.ec2; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.UserInfo; public class SshUtil { public static void scp(String keyPath, String sourcePath, String targetHostName, String targetFileName) throws IOException { try { File keyFile = new File(keyPath); JSch jsch = new JSch(); jsch.addIdentity(keyFile.getAbsolutePath()); Session session = jsch.getSession("root", targetHostName, 22); UserInfo ui = new SshUser(); session.setUserInfo(ui); session.connect(); String command = "scp -p -t " + targetFileName; Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand(command); // get I/O streams for remote scp OutputStream out = channel.getOutputStream(); InputStream in = channel.getInputStream(); channel.connect(); if (checkAck(in) != 0) { throw new RuntimeException("Failed to scp key file"); } // send "C0644 filesize filename", where filename should not include // '/' long filesize = (new File(sourcePath)).length(); command = "C0644 " + filesize + " "; if (sourcePath.lastIndexOf('/') > 0) { command += sourcePath.substring(sourcePath.lastIndexOf('/') + 1); } else { command += sourcePath; } command += "\n"; out.write(command.getBytes()); out.flush(); if (checkAck(in) != 0) { // this actually will never happend since checkAck already // throws an exception now. throw new RuntimeException("Fatal Error scp key file"); } // send a content of lfile FileInputStream fis = new FileInputStream(sourcePath); byte[] buf = new byte[1024]; while (true) { int len = fis.read(buf, 0, buf.length); if (len <= 0) break; out.write(buf, 0, len); // out.flush(); } fis.close(); fis = null; // send '\0' buf[0] = 0; out.write(buf, 0, 1); out.flush(); if (checkAck(in) != 0) { throw new RuntimeException("Failed to scp file"); } out.close(); channel.disconnect(); session.disconnect(); } catch (JSchException e) { throw new IOException("Unable to copy key file to host: ", e); } } public static boolean sshRemoteCommand(String dnsName, String command, String keyPath) throws IOException { try { File file = new File(keyPath); JSch jsch = new JSch(); jsch.addIdentity(file.getAbsolutePath()); Session session = jsch.getSession("root", dnsName, 22); UserInfo ui = new SshUser(); session.setUserInfo(ui); session.connect(); Channel channel = session.openChannel("exec"); ((ChannelExec) channel).setCommand(command); ((ChannelExec) channel).setErrStream(System.out); InputStream in = channel.getInputStream(); channel.connect(); byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; // we acully dont want to show the output // System.out.print(new String(tmp, 0, i)); } if (channel.isClosed()) { // System.out.println("exit-status: " + // channel.getExitStatus()); if (channel.getExitStatus() != 0) { return false; } break; } try { Thread.sleep(1000); } catch (InterruptedException ee) { Thread.currentThread().interrupt(); } } channel.disconnect(); session.disconnect(); } catch (JSchException e) { return false; // throw new IOException("Unable to ssh into master", e); } return true; } static class SshUser implements UserInfo { @Override public String getPassphrase() { return ""; } @Override public String getPassword() { return ""; } @Override public boolean promptPassphrase(String arg0) { return true; } @Override public boolean promptPassword(String arg0) { return true; } @Override public boolean promptYesNo(String arg0) { return true; } @Override public void showMessage(String arg0) { System.out.println(arg0); } } /** * from the jsch examples */ private static int checkAck(InputStream in) throws IOException { int b = in.read(); // b may be 0 for success, // 1 for error, // 2 for fatal error, // -1 if (b == 0) return b; if (b == -1) return b; if (b == 1 || b == 2) { StringBuffer sb = new StringBuffer(); int c; do { c = in.read(); sb.append((char) c); } while (c != '\n'); if (b == 1) { // error System.err.println("Ec2Hadoop.checkAck(): " + sb.toString()); throw new IOException("Error scp file: " + sb.toString()); // System.out.print(sb.toString()); } if (b == 2) { // fatal error throw new IOException("Fatal error scp key file: " + sb.toString()); // System.out.print(sb.toString()); } } return b; } }