Documentation ¶
Overview ¶
Provides an interface to the ssh package that allows a local script (shell or python) to be read and sent to a remote host for execution. The standard error and output are returned. Ssh connections are established using one or more private key files that are supplied when the broker object is created, and the connections persist until the object is closed allowing for subsequent commands to be executed without the overhead of the ssh setup.
Scripts must start with a #! line which is used to execute the interpreter on the remote host. The script is then written on stdin to the interpreter. If python is in the #! line, then leading whitespace isn't stripped as the script is sent to the remote host. Commented lines (beginning with #), and blank lines are removed (might cause issues for strings with embedded newlines, but for now I'm not worrying about those).
When the broker object is created, a single script initiator is started, however it is possible for the user application to start additional initiators in order to execute scripts in parallel. The initiators read from the queue of scripts to run and create a session, send the script, and wait for the results which are returned to the caller directly, or as a message structure on a channel, depending on which function was used.
There also seems to be a limit on the max number of concurrent sessions that one SSH connection will support. This seems to be a host policy, rather than a blanket SSH constant, so an initiator will retry the execution of a script when it appears that the failure is related to this limit. All other errors are returned to the caller for evaluation and possible retry.
There are two functions that the user can invoke to run a script on a remote host: Run_on_host() and NBRun_on_host(). The former will block until the command is run and the latter will queue the request with the caller's channel and the results message will be written to the channel when the script execution has been completed.
Basic usage: (error checking omitted)
// supply the key filenames that are recognised on the remote side in authorised keys keys := []string { "/home/scooter/.ssh/id_rsa", "/home/scooter/.ssh/id_dsa" } broker := Mk_broker( "scooter", keys ) // create a broker for user, with keys host := "cheetah" script := "/user/bin/do_something" // can be in PATH, or qualified parms := "-t 10 /tmp/output" // command line parameters env := "/tmp/envfile" // file containing environment stdout, stderr, err := broker.Run_on_host( host, script, parms, env )
The script may be Korn shell, bash, or python and is fed into the interpreter as standard input, so $0 (arg[0]) will not be set. The broker will attempt to set the variable ARGV0 to be the script name should the script need it. Other than this small difference, and there not being any standard input, the script should function as written. It is possible that other script types can be used, though it is known that #!/usr/bin/env awk will fail and thus "pure awk" must be wrapped inside of a ksh or bash script.
There are also two functions which support the running af a command on the remote host in a "traditional" SSH fashion. Run_cmd (blocking) and NBRun_cmd (non-blocking) run the command in a similar fashion as the script execution methods.
The user can also associate an rsync command to be executed on each successful connection to a host. This is done using the Add_rsync() function which supplies a list of files (space separated) and a directory to which they are to be placed on the remote hosts. The directory name should have a trailing slant (/) to ensure that rsync properly creates it. Because it _might_ be acceptable to the caller that the directory does not need a slant, this code will not add one if it is missing.
Index ¶
- type Broker
- func (b *Broker) Add_rsync(src *string, dest_dir *string)
- func (b *Broker) Close()
- func (b *Broker) Close_session(name *string) (err error)
- func (b *Broker) NBRun_cmd(host string, cmd string, uid int, uch chan *Broker_msg) (err error)
- func (b *Broker) NBRun_on_host(host string, script string, parms string, uid int, uch chan *Broker_msg) (err error)
- func (b *Broker) Reset()
- func (b *Broker) Rm_rsync()
- func (b *Broker) Run_cmd(host string, cmd string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error)
- func (b *Broker) Run_on_host(host string, script string, parms string, env_file string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error)
- func (b *Broker) Set_verbose(value bool)
- func (b *Broker) Start_initiators(n int)
- type Broker_msg
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Broker ¶
type Broker struct {
// contains filtered or unexported fields
}
------ public structures -----------------------------------------------------------------------------
Manages connection by host name, and the configuration that is needed to create a new session. Struct returned by Mk_broker
func Mk_broker ¶
Mk_broker creates a broker for the given user and with the given key files. If keys are given, then the assumption is that there should _not_ be any prompt for password. If keys is nil, then prompting will be allowed.
func (*Broker) Add_rsync ¶
Add_rsync accepts the setup for rsync commands. We assume src is one or more source files and dest_dir is the name of the directory on the remote host. When the rsync command is actually run, the two strings are combined (unchanged) with user@host: inserted just before the dest directory.
func (*Broker) Close ¶
func (b *Broker) Close()
Close cleans up things that need to be closed when the user makes us go away.
func (*Broker) Close_session ¶
Close_session closes a session to the named host.
func (*Broker) NBRun_cmd ¶
NBRun_cmd runs a command on the remote host, non-blocking. The cmd string is expected to be the complete command line.
func (*Broker) NBRun_on_host ¶
func (b *Broker) NBRun_on_host(host string, script string, parms string, uid int, uch chan *Broker_msg) (err error)
NBRun_on_host runs the execution request onto the initiator queue, but do not block. The response is put onto the channel provided by the user. If the channel is nil, the request is still queued with the assumption that the caller does not want the results.
func (*Broker) Run_cmd ¶
func (b *Broker) Run_cmd(host string, cmd string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error)
Run_cmd executes the command on the named host. The cmd string is expected to be the complete command line.
func (*Broker) Run_on_host ¶
func (b *Broker) Run_on_host(host string, script string, parms string, env_file string) (stdout *bytes.Buffer, stderr *bytes.Buffer, err error)
Run_on_host executes the script (a local shell/python script) on the remote host. This is done by creating a request and putting it on the initiator queue and waiting for the response on the dedicated channel allocated here.
A nil error indicates success, otherwise there was an error setting up for or executing the command. If stderr is nil, the error was related to setup rather than execution.
func (*Broker) Start_initiators ¶
Start_initiators starts n initiators which allow n scripts to be executed in parallel.
type Broker_msg ¶
type Broker_msg struct {
// contains filtered or unexported fields
}
Used to pass information into an initiator and then back to the requestor. External users (non-package functions) can use the get functions related to this struct to extract information (none of the information is directly available).
func (*Broker_msg) Get_info ¶
func (m *Broker_msg) Get_info() (host string, sname string, id int)
Returns the host, script name and ID contained in the
func (*Broker_msg) Get_results ¶
func (m *Broker_msg) Get_results() (stdout bytes.Buffer, stderr bytes.Buffer, elapsed int64, err error)
----- public msg functions ------------------------------------------------------------------------------
Get_results returns the standard out, standard error elapsed time (sec) and the overall error state contained in the message.