# -*- tcl -*- # Maintenance Instruction: leave the 999999.xxx.x as is and use punkshell 'dev make' or bin/punkmake to update from -buildversion.txt # module template: punkshell/src/decktemplates/vendor/punk/modules/template_module-0.0.2.tm # # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # (C) 2009 Jose F. Nieves # # @@ Meta Begin # Application punk::sshrun 999999.0a1.0 # Meta platform tcl # Meta license ISC # @@ Meta End # Copyright (c) 2009 Jose F. Nieves # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # doctools header # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools #[manpage_begin punkshell_module_punk::sshrun 0 999999.0a1.0] #[copyright "2009"] #[titledesc {Tcl procedures to execute tcl scripts in remote hosts}] [comment {-- Name section and table of contents description --}] #[moddesc {punk::sshrun tclssh clone}] [comment {-- Description at end of page heading --}] #[require punk::sshrun] #[keywords module ssh] #[description] #[para] This is a clone of tclssh by Jose F. Nieves #[para] The original repo is at: https://bitbucket.org/noaaport/tclssh/src/master/ #[para] This version is namespaced under punk::sshrun specifically for the Punk shell project - and may lag the original project or diverge. #[para] You are encouraged to use the original Tclssh source from the above URL for your own projects # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools #[section Overview] #[para] overview of punk::sshrun #[para] SYNOPSIS #[para] package require punk::sshrun #[para] - #[para] punk::sshrun::connect [lb]-t [rb] [lb]-- [rb] [lb]@[rb] #[para] Defaults: -t tclsh #[subsection Concepts] #[para] - ####### original wiki documentation ## Overview ## Tclssh is a package of pure Tcl functions for executing Tcl scripts in a remote host. It is used by Nbsp and the WRFPak to offload some long-time running jobs in parallel to other computers. ## ## The remote host must be accessible via ssh keys without a password; that is, for example, the contents of your ./ssh/id_rsa.pub must be added to the .ssh/authorized_keys file in the remote host. ## ## The directory ## ## /share/doc/examples ## has several examples that can be used for testing and documentation. ## ## Example ## The best way to explain how to use is by looking at one of them, ex-1.tcl. ## ## #!/usr/bin/tclsh ## ## package require ssh ## ## # ## # Collect in the string "script" the script that will be sent to the ## # remote (slave) host. ## # ## set script { ## puts "I am a remote host named [info hostname] executing a script ## that my master sent me. I am going to sent him back the results of some ## commands. Here they are: ## ## The date is: [exec date] ## My info is: [exec uname -a] ## ## Now I need to inform my master that I have finished. ## ## DONE 0" ## }; ## ## set slave "is.1-loop.net"; # This is the remote host ## ## # ## # If the tcl shell in the remote host is just "tclsh" (e.g. a linux system) ## # the -t option (and its argment) can be omitted; otherwise it can be ## # used to specify the name of the remote tcl shell. ## # ## ::ssh::connect -t tclsh8.6 -- $slave ## ::ssh::push $slave $script ## ::ssh::send $slave; ## while {[::ssh::pop_line $slave line] >= 0} { ## if {[regexp {^DONE\s+(\d+)} $line match code]} { ## break; ## } ## puts $line; ## } ## ::ssh::disconnect $slave; ## ## puts "Slave finished with code: $code"; ## Below is the output of executing ex-1.tcl from a machine named elite: ## ## [nieves@elite examples]$ ./ex-1.tcl ## I am a remote host named is.1-loop.net executing a script ## that my master sent me. I am going to sent him back the results of some ## commands. Here they are: ## ## The date is: Sun Dec 9 17:35:43 AST 2012 ## My info is: Linux is 2.6.32-308.8.2.el5.028stab101.1 #1 SMP Sun Jun 24 20:25:35 MSD 2012 i686 GNU/Linux ## ## Now I need to inform my master that I have finished. ## Slave finished with code: 0 ## [nieves@elite examples]$ ## Several other examples in the ## ## /share/doc/examples ## directory illustrate more capabilities of this package. # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ ## Requirements # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools #[subsection dependencies] #[para] packages used by punk::sshrun #[list_begin itemized] package require Tcl 8.6- package require cmdline #*** !doctools #[item] [package {Tcl 8.6}] #[item] [package {cmdline}] # #package require frobz # #*** !doctools # #[item] [package {frobz}] #*** !doctools #[list_end] # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ #*** !doctools #[section API] # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # oo::class namespace # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ namespace eval punk::sshrun::class { #*** !doctools #[subsection {Namespace punk::sshrun::class}] #[para] class definitions if {[info commands [namespace current]::interface_sample1] eq ""} { #*** !doctools #[list_begin enumerated] # oo::class create interface_sample1 { # #*** !doctools # #[enum] CLASS [class interface_sample1] # #[list_begin definitions] # method test {arg1} { # #*** !doctools # #[call class::interface_sample1 [method test] [arg arg1]] # #[para] test method # puts "test: $arg1" # } # #*** !doctools # #[list_end] [comment {-- end definitions interface_sample1}] # } #*** !doctools #[list_end] [comment {--- end class enumeration ---}] } } # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ # Base namespace # ++ +++ +++ +++ +++ +++ +++ +++ +++ +++ +++ namespace eval punk::sshrun { namespace export * variable ssh; array set ssh {}; #*** !doctools #[subsection {Namespace punk::sshrun}] #[para] Core API functions for punk::sshrun #[list_begin definitions] proc connect {args} { #*** !doctools #[call connect [arg args]] #[para] Must be called first. #[para] This proc opens an io channel to the tclsh in the remote host (via ssh) that is kept in an internal variable for subsequent use. #[para] The file handle can be retrieved if desired through the command: get_filehandle {host} variable ssh; set usage {connect [-t ] [-- ] [@]}; set optlist {{t.arg "tclsh"}}; array set option [::cmdline::getoptions args $optlist $usage]; set cmd [concat "|ssh" $args $option(t) 2>@ stdout]; set F [open $cmd r+]; set host [lindex $args end]; if {[regexp {(.*)@(.*)} $host match s1 s2]} { set user $s1; set host $s2; } # These are the only internal variables (apart from the "user" variables). set ssh($host,F) $F; set ssh($host,script) [list]; } proc disconnect {host} { #*** !doctools # [call disconnect [arg host]] # [para] Must be called last. Closes the filehandle opened by connect. variable ssh; system::_verify_connection $host; set status [catch { close $ssh($host,F); } errmsg]; unset ssh($host,F); unset ssh($host,script); if {$status != 0} { return -code error $errmsg; } } proc push {host script} { #*** !doctools # [call push [arg host] [arg script]] # [para]