X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.support.simple%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fjsch%2FRemoteExec.java;h=b9eae87ac19b215fd444de23525233bce294d640;hb=9b2422e7198df6f34282a805058dd5f497417318;hp=d07e6ab6cf4273924f87ab1ecf9e18088c9e648c;hpb=67f896c4f853b336046d8586ec514c96f468c88a;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java index d07e6ab6c..b9eae87ac 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/RemoteExec.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2010 Mathieu Baudier + * + * 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 org.argeo.slc.jsch; import java.io.BufferedReader; @@ -16,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.StringTokenizer; +import org.apache.commons.exec.ExecuteStreamHandler; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -48,6 +65,11 @@ public class RemoteExec extends AbstractJschTask { private Resource stdOut = null; private ExecutionResources executionResources; + private String user; + + private ExecuteStreamHandler streamHandler = null; + + private Integer lastExitStatus = null; /** * If set, stdout is written to it as a list of lines. Cleared before each * run. @@ -56,6 +78,14 @@ public class RemoteExec extends AbstractJschTask { private Boolean logEvenIfStdOutLines = false; private Boolean quiet = false; + public RemoteExec() { + } + + public RemoteExec(SshTarget sshTarget, String cmd) { + setSshTarget(sshTarget); + setCommand(cmd); + } + public void run(Session session) { List commandsToUse = new ArrayList(commands); String commandToUse = command; @@ -80,8 +110,8 @@ public class RemoteExec extends AbstractJschTask { throw new SlcException("Cannot specify commands and script"); BufferedReader reader = null; try { - reader = new BufferedReader(new InputStreamReader(script - .getInputStream())); + reader = new BufferedReader(new InputStreamReader( + script.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { if (!StringUtils.hasText(line)) @@ -96,9 +126,17 @@ public class RemoteExec extends AbstractJschTask { } if (forceShell) { - if (commandToUse.indexOf(';') >= 0 - || commandToUse.indexOf('\n') >= 0) { - StringTokenizer st = new StringTokenizer(commandToUse, ";\n"); + // for the time being do not interpret both \n and ; + // priority to \n + // until we know how to parse ; within "" + if (commandToUse.indexOf('\n') >= 0) { + StringTokenizer st = new StringTokenizer(commandToUse, "\n"); + while (st.hasMoreTokens()) { + String cmd = st.nextToken(); + commandsToUse.add(cmd); + } + } else if (commandToUse.indexOf(';') >= 0) { + StringTokenizer st = new StringTokenizer(commandToUse, ";"); while (st.hasMoreTokens()) { String cmd = st.nextToken(); commandsToUse.add(cmd); @@ -109,6 +147,19 @@ public class RemoteExec extends AbstractJschTask { commandToUse = null; } + // run as user + if (user != null) { + if (commandsToUse.size() > 0) { + commandsToUse.add(0, "su - " + user); + commandsToUse.add("exit"); + } else { + if (command.indexOf('\"') >= 0) + throw new SlcException( + "Don't know how to su a command with \", use shell instead."); + commandToUse = "su - " + user + " -c \"" + command + "\""; + } + } + // execute command(s) if (commandToUse != null) { if (commandsToUse.size() != 0) @@ -209,25 +260,20 @@ public class RemoteExec extends AbstractJschTask { log.debug("Run '" + command + "' on " + getSshTarget() + "..."); channel.connect(); - if (stdIn != null) { - Thread stdInThread = new Thread("Stdin " + getSshTarget()) { - @Override - public void run() { - OutputStream out = null; - try { - out = channel.getOutputStream(); - IOUtils.copy(stdIn.getInputStream(), out); - } catch (IOException e) { - throw new SlcException("Cannot write stdin on " - + getSshTarget(), e); - } finally { - IOUtils.closeQuietly(out); - } + readStdIn(channel); + readStdOut(channel); + + if (streamHandler != null){ + streamHandler.start(); + while(!channel.isClosed()){ + try { + Thread.sleep(100); + } catch (Exception e) { + break; } - }; - stdInThread.start(); + } } - readStdOut(channel); + checkExitStatus(channel); channel.disconnect(); } catch (Exception e) { @@ -236,76 +282,117 @@ public class RemoteExec extends AbstractJschTask { } } - protected void readStdErr(final ChannelExec channel) { - new Thread("stderr " + getSshTarget()) { - public void run() { - BufferedReader stdErr = null; + protected void readStdOut(Channel channel) { + try { + if (stdOut != null) { + OutputStream localStdOut = createOutputStream(stdOut); + try { + IOUtils.copy(channel.getInputStream(), localStdOut); + } finally { + IOUtils.closeQuietly(localStdOut); + } + } else if (streamHandler != null) { + if (channel.getInputStream() != null) + streamHandler.setProcessOutputStream(channel + .getInputStream()); + } else { + BufferedReader stdOut = null; try { - InputStream in = channel.getErrStream(); - stdErr = new BufferedReader(new InputStreamReader(in)); + InputStream in = channel.getInputStream(); + stdOut = new BufferedReader(new InputStreamReader(in)); String line = null; - while ((line = stdErr.readLine()) != null) { - if (!line.trim().equals("")) - log.error(line); + while ((line = stdOut.readLine()) != null) { + if (!line.trim().equals("")) { + + if (stdOutLines != null) { + stdOutLines.add(line); + if (logEvenIfStdOutLines && !quiet) + log.info(line); + } else { + if (!quiet) + log.info(line); + } + } } - } catch (IOException e) { - if (log.isDebugEnabled()) - log.error("Cannot read stderr from " + getSshTarget(), - e); } finally { - IOUtils.closeQuietly(stdErr); + IOUtils.closeQuietly(stdOut); } } - }.start(); + } catch (IOException e) { + throw new SlcException("Cannot redirect stdout from " + + getSshTarget(), e); + } } - protected void readStdOut(Channel channel) { - if (stdOut != null) { - OutputStream localStdOut = createOutputStream(stdOut); + protected void readStdErr(final ChannelExec channel) { + if (streamHandler != null) { try { - IOUtils.copy(channel.getInputStream(), localStdOut); + streamHandler.setProcessOutputStream(channel.getErrStream()); } catch (IOException e) { - throw new SlcException("Cannot redirect stdout", e); - } finally { - IOUtils.closeQuietly(localStdOut); + throw new SlcException("Cannot read stderr from " + + getSshTarget(), e); } } else { - BufferedReader stdOut = null; - try { - InputStream in = channel.getInputStream(); - stdOut = new BufferedReader(new InputStreamReader(in)); - String line = null; - while ((line = stdOut.readLine()) != null) { - if (!line.trim().equals("")) { - - if (stdOutLines != null) { - stdOutLines.add(line); - if (logEvenIfStdOutLines && !quiet) - log.info(line); - } else { - if (!quiet) - log.info(line); + new Thread("stderr " + getSshTarget()) { + public void run() { + BufferedReader stdErr = null; + try { + InputStream in = channel.getErrStream(); + stdErr = new BufferedReader(new InputStreamReader(in)); + String line = null; + while ((line = stdErr.readLine()) != null) { + if (!line.trim().equals("")) + log.error(line); } + } catch (IOException e) { + if (log.isDebugEnabled()) + log.error("Cannot read stderr from " + + getSshTarget(), e); + } finally { + IOUtils.closeQuietly(stdErr); } } + }.start(); + } + } + + protected void readStdIn(final ChannelExec channel) { + if (stdIn != null) { + Thread stdInThread = new Thread("Stdin " + getSshTarget()) { + @Override + public void run() { + OutputStream out = null; + try { + out = channel.getOutputStream(); + IOUtils.copy(stdIn.getInputStream(), out); + } catch (IOException e) { + throw new SlcException("Cannot write stdin on " + + getSshTarget(), e); + } finally { + IOUtils.closeQuietly(out); + } + } + }; + stdInThread.start(); + } else if (streamHandler != null) { + try { + streamHandler.setProcessInputStream(channel.getOutputStream()); } catch (IOException e) { - if (log.isDebugEnabled()) - log.error("Cannot read stdout from " + getSshTarget(), e); - } finally { - IOUtils.closeQuietly(stdOut); + throw new SlcException("Cannot write stdin on " + + getSshTarget(), e); } } } protected void checkExitStatus(Channel channel) { if (channel.isClosed()) { - int exitStatus = channel.getExitStatus(); - if (exitStatus == 0) { + lastExitStatus = channel.getExitStatus(); + if (lastExitStatus == 0) { if (log.isTraceEnabled()) - log.trace("Remote execution exit status: " + exitStatus); + log.trace("Remote execution exit status: " + lastExitStatus); } else { String msg = "Remote execution failed with " + " exit status: " - + exitStatus; + + lastExitStatus; if (failOnBadExitStatus) throw new SlcException(msg); else @@ -332,6 +419,14 @@ public class RemoteExec extends AbstractJschTask { return out; } + public Integer getLastExitStatus() { + return lastExitStatus; + } + + public void setStreamHandler(ExecuteStreamHandler executeStreamHandler) { + this.streamHandler = executeStreamHandler; + } + public void setCommand(String command) { this.command = command; } @@ -400,4 +495,8 @@ public class RemoteExec extends AbstractJschTask { this.executionResources = executionResources; } + public void setUser(String user) { + this.user = user; + } + }