All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hidetake.groovy.ssh.operation.Shell.groovy Maven / Gradle / Ivy

There is a newer version: 2.11.2
Show newest version
package org.hidetake.groovy.ssh.operation

import com.jcraft.jsch.ChannelShell
import groovy.util.logging.Slf4j
import org.hidetake.groovy.ssh.connection.Connection
import org.hidetake.groovy.ssh.core.settings.LoggingMethod
import org.hidetake.groovy.ssh.core.type.InputStreamValue
import org.hidetake.groovy.ssh.interaction.InteractionHandler
import org.hidetake.groovy.ssh.interaction.Interactions
import org.hidetake.groovy.ssh.interaction.Stream
import org.hidetake.groovy.ssh.util.ManagedBlocking

/**
 * A shell operation.
 *
 * @author Hidetake Iwata
 */
@Slf4j
class Shell implements Operation {
    private final Connection connection
    private final ChannelShell channel
    private final Interactions interactions
    private final int channelConnectionTimeoutSec

    def Shell(Connection connection1, ShellSettings settings) {
        connection = connection1
        channel = connection.createShellChannel()
        channel.agentForwarding = settings.agentForwarding
        channelConnectionTimeoutSec = settings.timeoutSec

        interactions = new Interactions(channel.outputStream, channel.inputStream, settings.encoding)
        if (settings.inputStream) {
            def inputStreamValue = new InputStreamValue(settings.inputStream)
            interactions.add {
                standardInput.withStream {
                    log.debug("Sending to standard input on command $connection.remote.name#$channel.id")
                    inputStreamValue >> standardInput
                }
            }
        }
        if (settings.outputStream) {
            interactions.pipe(Stream.StandardOutput, settings.outputStream)
        }
        if (settings.logging == LoggingMethod.slf4j) {
            def log = Shell.log  // workaround for mock injection in test code
            interactions.add {
                when(line: _, from: standardOutput) {
                    log.info("$connection.remote.name#$channel.id|$it")
                }
                when(line: _, from: standardError) {
                    log.error("$connection.remote.name#$channel.id|$it")
                }
            }
        } else if (settings.logging == LoggingMethod.stdout) {
            interactions.add {
                when(line: _, from: standardOutput) {
                    System.out.println("$connection.remote.name#$channel.id|$it")
                }
                when(line: _, from: standardError) {
                    System.err.println("$connection.remote.name#$channel.id|$it")
                }
            }
        }
        if (settings.interaction) {
            interactions.add(settings.interaction)
        }
    }

    @Override
    int execute() {
        channel.connect(channelConnectionTimeoutSec * 1000)
        try {
            log.info("Started shell $connection.remote.name#$channel.id")
            interactions.start()
            interactions.waitForEndOfStream()
            ManagedBlocking.until {
                channel.closed
            }

            int exitStatus = channel.exitStatus
            if (exitStatus == 0) {
                log.info("Success shell $connection.remote.name#$channel.id")
            } else {
                log.error("Failed shell $connection.remote.name#$channel.id with status $exitStatus")
            }
            exitStatus
        } finally {
            channel.disconnect()
        }
    }

    @Override
    void addInteraction(@DelegatesTo(InteractionHandler) Closure closure) {
        interactions.add(closure)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy