📄 sshexec.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.tools.ant.taskdefs.optional.ssh;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.StringReader;import org.apache.tools.ant.BuildException;import org.apache.tools.ant.Project;import org.apache.tools.ant.types.Resource;import org.apache.tools.ant.types.resources.FileResource;import org.apache.tools.ant.util.FileUtils;import org.apache.tools.ant.util.KeepAliveOutputStream;import org.apache.tools.ant.util.TeeOutputStream;import com.jcraft.jsch.ChannelExec;import com.jcraft.jsch.JSchException;import com.jcraft.jsch.Session;/** * Executes a command on a remote machine via ssh. * @since Ant 1.6 (created February 2, 2003) */public class SSHExec extends SSHBase { private static final int BUFFER_SIZE = 8192; private static final int RETRY_INTERVAL = 500; /** the command to execute via ssh */ private String command = null; /** units are milliseconds, default is 0=infinite */ private long maxwait = 0; /** for waiting for the command to finish */ private Thread thread = null; private String outputProperty = null; // like <exec> private File outputFile = null; // like <exec> private boolean append = false; // like <exec> private Resource commandResource = null; private static final String TIMEOUT_MESSAGE = "Timeout period exceeded, connection dropped."; /** * Constructor for SSHExecTask. */ public SSHExec() { super(); } /** * Sets the command to execute on the remote host. * * @param command The new command value */ public void setCommand(String command) { this.command = command; } /** * Sets a commandResource from a file * @param f the value to use. * @since Ant 1.7.1 */ public void setCommandResource(String f) { this.commandResource = new FileResource(new File(f)); } /** * The connection can be dropped after a specified number of * milliseconds. This is sometimes useful when a connection may be * flaky. Default is 0, which means "wait forever". * * @param timeout The new timeout value in seconds */ public void setTimeout(long timeout) { maxwait = timeout; } /** * If used, stores the output of the command to the given file. * * @param output The file to write to. */ public void setOutput(File output) { outputFile = output; } /** * Determines if the output is appended to the file given in * <code>setOutput</code>. Default is false, that is, overwrite * the file. * * @param append True to append to an existing file, false to overwrite. */ public void setAppend(boolean append) { this.append = append; } /** * If set, the output of the command will be stored in the given property. * * @param property The name of the property in which the command output * will be stored. */ public void setOutputproperty(String property) { outputProperty = property; } /** * Execute the command on the remote host. * * @exception BuildException Most likely a network error or bad parameter. */ public void execute() throws BuildException { if (getHost() == null) { throw new BuildException("Host is required."); } if (getUserInfo().getName() == null) { throw new BuildException("Username is required."); } if (getUserInfo().getKeyfile() == null && getUserInfo().getPassword() == null) { throw new BuildException("Password or Keyfile is required."); } if (command == null && commandResource == null) { throw new BuildException("Command or commandResource is required."); } Session session = null; try { session = openSession(); /* called once */ if (command != null) { log("cmd : " + command, Project.MSG_INFO); ByteArrayOutputStream out = executeCommand(session, command); if (outputProperty != null) { //#bugzilla 43437 getProject().setNewProperty(outputProperty, command + " : " + out); } } else { // read command resource and execute for each command try { BufferedReader br = new BufferedReader( new InputStreamReader(commandResource.getInputStream())); String cmd; String output = ""; while ((cmd = br.readLine()) != null) { log("cmd : " + cmd, Project.MSG_INFO); ByteArrayOutputStream out = executeCommand(session, cmd); output += cmd + " : " + out + "\n"; } if (outputProperty != null) { //#bugzilla 43437 getProject().setNewProperty(outputProperty, output); } FileUtils.close(br); } catch (IOException e) { throw new BuildException(e); } } } catch (JSchException e) { throw new BuildException(e); } finally { if (session != null && session.isConnected()) { session.disconnect(); } } } private ByteArrayOutputStream executeCommand(Session session, String cmd) throws BuildException { ByteArrayOutputStream out = new ByteArrayOutputStream(); TeeOutputStream tee = new TeeOutputStream(out, new KeepAliveOutputStream(System.out)); try { final ChannelExec channel; session.setTimeout((int) maxwait); /* execute the command */ channel = (ChannelExec) session.openChannel("exec"); channel.setCommand(cmd); channel.setOutputStream(tee); channel.setExtOutputStream(tee); channel.connect(); // wait for it to finish thread = new Thread() { public void run() { while (!channel.isClosed()) { if (thread == null) { return; } try { sleep(RETRY_INTERVAL); } catch (Exception e) { // ignored } } } }; thread.start(); thread.join(maxwait); if (thread.isAlive()) { // ran out of time thread = null; if (getFailonerror()) { throw new BuildException(TIMEOUT_MESSAGE); } else { log(TIMEOUT_MESSAGE, Project.MSG_ERR); } } else { //success if (outputFile != null) { writeToFile(out.toString(), append, outputFile); } // this is the wrong test if the remote OS is OpenVMS, // but there doesn't seem to be a way to detect it. int ec = channel.getExitStatus(); if (ec != 0) { String msg = "Remote command failed with exit status " + ec; if (getFailonerror()) { throw new BuildException(msg); } else { log(msg, Project.MSG_ERR); } } } } catch (BuildException e) { throw e; } catch (JSchException e) { if (e.getMessage().indexOf("session is down") >= 0) { if (getFailonerror()) { throw new BuildException(TIMEOUT_MESSAGE, e); } else { log(TIMEOUT_MESSAGE, Project.MSG_ERR); } } else { if (getFailonerror()) { throw new BuildException(e); } else { log("Caught exception: " + e.getMessage(), Project.MSG_ERR); } } } catch (Exception e) { if (getFailonerror()) { throw new BuildException(e); } else { log("Caught exception: " + e.getMessage(), Project.MSG_ERR); } } return out; } /** * Writes a string to a file. If destination file exists, it may be * overwritten depending on the "append" value. * * @param from string to write * @param to file to write to * @param append if true, append to existing file, else overwrite * @exception Exception most likely an IOException */ private void writeToFile(String from, boolean append, File to) throws IOException { FileWriter out = null; try { out = new FileWriter(to.getAbsolutePath(), append); StringReader in = new StringReader(from); char[] buffer = new char[BUFFER_SIZE]; int bytesRead; while (true) { bytesRead = in.read(buffer); if (bytesRead == -1) { break; } out.write(buffer, 0, bytesRead); } out.flush(); } finally { if (out != null) { out.close(); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -