move weirder example code here
Signed-off-by: Jeff Carr <jcarr@wit.com>
This commit is contained in:
parent
0a0f11d4f1
commit
2960a05ed3
|
@ -0,0 +1,11 @@
|
|||
all:
|
||||
# go build
|
||||
GO111MODULE="off" go run main.go
|
||||
|
||||
goimports:
|
||||
goimports -w *.go
|
||||
|
||||
redomod:
|
||||
rm -f go.*
|
||||
GO111MODULE= go mod init
|
||||
GO111MODULE= go mod tidy
|
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
import "log"
|
||||
import "reflect"
|
||||
*/
|
||||
|
||||
import "os"
|
||||
|
||||
// import "github.com/davecgh/go-spew/spew"
|
||||
|
||||
import "go.wit.com/lib/gui/shell"
|
||||
|
||||
func main() {
|
||||
shell.Run("ls /tmp")
|
||||
|
||||
shell.Run("ping -c 3 localhost")
|
||||
|
||||
// slow down the polling to every 2 seconds
|
||||
shell.SetDelayInMsec(2000)
|
||||
|
||||
shell.Run("ping -c 4 localhost")
|
||||
|
||||
// capture ping output into a file
|
||||
fout, _ := os.Create("/tmp/example1.ping.stdout")
|
||||
ferr, _ := os.Create("/tmp/example1.ping.stderr")
|
||||
shell.SetStdout(fout)
|
||||
shell.SetStderr(ferr)
|
||||
|
||||
shell.Run("ping -c 5 localhost")
|
||||
|
||||
// turn out process exit debugging
|
||||
shell.SpewOn()
|
||||
|
||||
fout, _ = os.Create("/tmp/example1.fail.stdout")
|
||||
ferr, _ = os.Create("/tmp/example1.fail.stderr")
|
||||
shell.SetStdout(fout)
|
||||
shell.SetStderr(ferr)
|
||||
|
||||
// TODO: this might not be working
|
||||
// check error handling
|
||||
shell.Run("ls /tmpthisisnothere")
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
all:
|
||||
# go build
|
||||
GO111MODULE="off" go run main.go
|
|
@ -0,0 +1,11 @@
|
|||
package main
|
||||
|
||||
import "log"
|
||||
// import "fmt"
|
||||
import "go.wit.com/lib/gui/shell"
|
||||
|
||||
func main() {
|
||||
err := shell.Run("cat /etc/issue")
|
||||
log.Println("cat /etc/issue returned", err)
|
||||
// fmt.Print(output)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
//go:build linux && go1.7
|
||||
// +build linux,go1.7
|
||||
|
||||
// put stuff in here that you only want compiled under linux
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/wercker/journalhook"
|
||||
)
|
||||
|
||||
var sigChan chan os.Signal
|
||||
|
||||
func handleSignal(err interface{}, ret int) {
|
||||
log.Println("handleSignal() only should be compiled on linux")
|
||||
sigChan = make(chan os.Signal, 3)
|
||||
signal.Notify(sigChan, syscall.SIGUSR1)
|
||||
}
|
||||
|
||||
func UseJournalctl() {
|
||||
journalhook.Enable()
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/svent/go-nbreader"
|
||||
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
func (cmd *OldShell) Run(cmdline string) string {
|
||||
cmd.InitProcess(cmdline)
|
||||
if cmd.Error != nil {
|
||||
return ""
|
||||
}
|
||||
cmd.Exec(cmdline)
|
||||
return Chomp(cmd.Buffer)
|
||||
}
|
||||
|
||||
func (cmd *OldShell) InitProcess(cmdline string) {
|
||||
log.Log(RUN, "shell.InitProcess() START "+cmdline)
|
||||
|
||||
cmd.Cmdline = Chomp(cmdline) // this is like 'chomp' in perl
|
||||
cmdArgs := strings.Fields(cmd.Cmdline)
|
||||
if len(cmdArgs) == 0 {
|
||||
cmd.Error = fmt.Errorf("cmdline == ''")
|
||||
cmd.Done = true
|
||||
return
|
||||
}
|
||||
if cmdArgs[0] == "cd" {
|
||||
if len(cmdArgs) > 1 {
|
||||
log.Log(RUN, "os.Chdir()", cmd)
|
||||
os.Chdir(cmdArgs[1])
|
||||
}
|
||||
handleError(nil, 0)
|
||||
cmd.Done = true
|
||||
return
|
||||
}
|
||||
|
||||
cmd.Process = exec.Command(cmdArgs[0], cmdArgs[1:len(cmdArgs)]...)
|
||||
}
|
||||
|
||||
func (cmd *OldShell) FileCreate(out string) {
|
||||
var newfile File
|
||||
|
||||
var iof io.ReadCloser
|
||||
if out == "STDOUT" {
|
||||
iof, _ = cmd.Process.StdoutPipe()
|
||||
} else {
|
||||
iof, _ = cmd.Process.StderrPipe()
|
||||
}
|
||||
|
||||
newfile.Fio = iof
|
||||
newfile.Fbufio = bufio.NewReader(iof)
|
||||
// newfile.Fnbreader = nbreader.NewNBReader(newfile.Fbufio, 1024)
|
||||
|
||||
if out == "STDOUT" {
|
||||
cmd.STDOUT = &newfile
|
||||
} else {
|
||||
cmd.STDERR = &newfile
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this might cause problems:
|
||||
// always remove the newlines at the end ?
|
||||
func (cmd *OldShell) Exec(cmdline string) {
|
||||
log.Log(RUN, "shell.Run() START "+cmdline)
|
||||
|
||||
cmd.InitProcess(cmdline)
|
||||
if cmd.Error != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cmd.FileCreate("STDOUT")
|
||||
cmd.FileCreate("STDERR")
|
||||
|
||||
cmd.Process.Start()
|
||||
|
||||
// TODO; 'goroutine' both of these
|
||||
// and make your own wait that will make sure
|
||||
// the process is then done and run process.Wait()
|
||||
go cmd.Capture(cmd.STDERR)
|
||||
cmd.Capture(cmd.STDOUT)
|
||||
|
||||
// wait until the process exists
|
||||
// https://golang.org/pkg/os/exec/#Cmd.Wait
|
||||
// What should happen here, before calling Wait()
|
||||
// is checks to make sure the READERS() on STDOUT and STDERR are done
|
||||
err := cmd.Process.Wait()
|
||||
|
||||
// time.Sleep(2 * time.Second) // putting this here doesn't help STDOUT flush()
|
||||
|
||||
if err != nil {
|
||||
cmd.Fail = true
|
||||
cmd.Error = err
|
||||
log.Log(RUN, "process.Wait() END err =", err.Error())
|
||||
} else {
|
||||
log.Log(RUN, "process.Wait() END")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// nonblocking read until file errors
|
||||
func (cmd *OldShell) Capture(f *File) {
|
||||
log.Log(RUN, "nbrREADER() START")
|
||||
|
||||
if cmd.Buffer == nil {
|
||||
cmd.Buffer = new(bytes.Buffer)
|
||||
}
|
||||
if cmd.Buffer == nil {
|
||||
f.Dead = false
|
||||
cmd.Error = fmt.Errorf("could not make buffer")
|
||||
log.Error(cmd.Error, "f.Buffer == nil")
|
||||
log.Error(cmd.Error, "SHOULD DIE HERE")
|
||||
cmd.Done = true
|
||||
}
|
||||
|
||||
f.Dead = false
|
||||
|
||||
// loop that keeps trying to read from f
|
||||
for f.Dead == false {
|
||||
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // only check the buffer 500 times a second
|
||||
|
||||
// set to false so it keeps retrying reads
|
||||
f.Empty = false
|
||||
|
||||
// tight loop that reads 1024 bytes at a time until buffer is empty
|
||||
// 1024 is set in f.BufferSize
|
||||
for f.Empty == false {
|
||||
f.Empty = cmd.ReadToBuffer(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if filehandle buffer is empty
|
||||
func (cmd *OldShell) ReadToBuffer(f *File) bool {
|
||||
log.Log(RUN, "ReadToBuffer() START")
|
||||
// nbr := f.Fnbreader
|
||||
// newfile.Fnbreader = nbreader.NewNBReader(newfile.Fbufio, 1024)
|
||||
nbr := nbreader.NewNBReader(f.Fbufio, 1024)
|
||||
oneByte := make([]byte, 1024)
|
||||
if nbr == nil {
|
||||
// log.Debugln("ReadToBuffer() ERROR nbr is nil")
|
||||
f.Dead = true
|
||||
return true
|
||||
}
|
||||
count, err := nbr.Read(oneByte)
|
||||
f.TotalCount += count
|
||||
|
||||
if err != nil {
|
||||
// log.Debugln("ReadToBuffer() file has closed with", err)
|
||||
// log.Debugln("ReadToBuffer() count = ", count, "err = ", err)
|
||||
f.Dead = true
|
||||
return true
|
||||
}
|
||||
if count == 0 {
|
||||
// log.Debugln("ReadToBuffer() START count == 0 return true")
|
||||
return true
|
||||
}
|
||||
// log.Debugln("ReadToBuffer() count = ", count)
|
||||
// tmp := Chomp(oneByte)
|
||||
// log.Debugln("ReadToBuffer() tmp = ", tmp)
|
||||
io.WriteString(cmd.Buffer, strings.Trim(string(oneByte), "\x00"))
|
||||
return false
|
||||
}
|
||||
|
||||
// pass in two file handles (1 read, 1 write)
|
||||
func nonBlockingReader(buffReader *bufio.Reader, writeFileHandle *os.File, stdout *bufio.Writer) {
|
||||
// newreader := bufio.NewReader(readFileHandle)
|
||||
|
||||
// create a nonblocking GO reader
|
||||
nbr := nbreader.NewNBReader(buffReader, 1024)
|
||||
|
||||
for {
|
||||
// defer buffReader.Close()
|
||||
// defer writeFileHandle.Flush()
|
||||
defer writeFileHandle.Close()
|
||||
totalCount := 0
|
||||
for {
|
||||
oneByte := make([]byte, 1024)
|
||||
count, err := nbr.Read(oneByte)
|
||||
if err != nil {
|
||||
log.Log(INFO, "count, err =", count, err)
|
||||
handleError(err, -1)
|
||||
return
|
||||
}
|
||||
totalCount += count
|
||||
if count == 0 {
|
||||
time.Sleep(time.Duration(msecDelay) * time.Millisecond) // without this delay this will peg the CPU
|
||||
if totalCount != 0 {
|
||||
log.Log(INFO, "STDERR: totalCount = ", totalCount)
|
||||
totalCount = 0
|
||||
}
|
||||
} else {
|
||||
log.Log(INFO, "STDERR: count = ", count)
|
||||
writeFileHandle.Write(oneByte[0:count])
|
||||
if quiet == false {
|
||||
stdout.Write(oneByte[0:count])
|
||||
stdout.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/tmc/scp"
|
||||
"go.wit.com/log"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
var sshHostname string
|
||||
var sshPort int
|
||||
var sshUsername string
|
||||
var sshPassword string
|
||||
var sshKeyfile string
|
||||
|
||||
func SSHclientSet(hostname string, port int, username string, pass string, keyfile string) {
|
||||
sshHostname = hostname
|
||||
sshPort = port
|
||||
sshUsername = username
|
||||
sshPassword = pass
|
||||
sshKeyfile = keyfile
|
||||
}
|
||||
|
||||
func SSHclientSCP(localfile string, remotefile string) {
|
||||
log.Log(SSH, "shell.SSHclientSCP() START")
|
||||
log.Log(SSH, "shell.SSHclientSCP() \tlocalfile =", localfile)
|
||||
log.Log(SSH, "shell.SSHclientSCP() \tremotefile =", remotefile)
|
||||
sess := mySsh(sshHostname, sshPort, sshUsername, sshPassword, sshKeyfile)
|
||||
err := scp.CopyPath(localfile, remotefile, sess)
|
||||
sess.Close()
|
||||
log.Log(SSH, "shell.SSHclientSCP() \tscp.CopyPath() err =", err)
|
||||
log.Log(SSH, "shell.SSHclientSCP() END")
|
||||
}
|
||||
|
||||
func SSHclientRun(cmd string) {
|
||||
log.Log(SSH, "shell.SSHclientRun() START cmd =", cmd)
|
||||
sess := mySsh(sshHostname, sshPort, sshUsername, sshPassword, sshKeyfile)
|
||||
err := sess.Run(cmd)
|
||||
sess.Close()
|
||||
log.Log(SSH, "shell.SSHclientRun() END err =", err)
|
||||
}
|
||||
|
||||
func mySsh(hostname string, port int, username string, pass string, keyfile string) *ssh.Session {
|
||||
// get host public key
|
||||
// hostKey := getHostKey(host)
|
||||
// log.Log(SSH, "hostkey =", hostKey)
|
||||
|
||||
publicKey, err := PublicKeyFile(keyfile)
|
||||
if err != nil {
|
||||
log.Log(SSH, "PublicKeyFile() error =", err)
|
||||
}
|
||||
|
||||
// ssh client config
|
||||
config := ssh.ClientConfig{
|
||||
User: username,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(pass),
|
||||
publicKey,
|
||||
},
|
||||
// allow any host key to be used (non-prod)
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
|
||||
// verify host public key
|
||||
// HostKeyCallback: ssh.FixedHostKey(hostKey),
|
||||
// optional host key algo list
|
||||
HostKeyAlgorithms: []string{
|
||||
ssh.KeyAlgoRSA,
|
||||
ssh.KeyAlgoDSA,
|
||||
ssh.KeyAlgoECDSA256,
|
||||
ssh.KeyAlgoECDSA384,
|
||||
ssh.KeyAlgoECDSA521,
|
||||
ssh.KeyAlgoED25519,
|
||||
},
|
||||
// optional tcp connect timeout
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
sport := fmt.Sprintf("%d", port)
|
||||
// connect
|
||||
client, err := ssh.Dial("tcp", hostname+":"+sport, &config)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
// defer client.Close()
|
||||
|
||||
// start session
|
||||
sess, err := client.NewSession()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
// defer sess.Close()
|
||||
|
||||
return sess
|
||||
}
|
||||
|
||||
func Scp(sess *ssh.Session, localfile string, remotefile string) {
|
||||
err := scp.CopyPath(localfile, remotefile, sess)
|
||||
log.Log(SSH, "scp.CopyPath() err =", err)
|
||||
}
|
||||
|
||||
func PublicKeyFile(file string) (ssh.AuthMethod, error) {
|
||||
buffer, err := ioutil.ReadFile(file)
|
||||
log.Log(SSH, "buffer =", string(buffer))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := ssh.ParsePrivateKey(buffer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ssh.PublicKeys(key), nil
|
||||
}
|
||||
|
||||
// THIS doesn't work
|
||||
/*
|
||||
func getHostKey(host string) ssh.PublicKey {
|
||||
// parse OpenSSH known_hosts file
|
||||
// ssh or use ssh-keyscan to get initial key
|
||||
file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
var hostKey ssh.PublicKey
|
||||
for scanner.Scan() {
|
||||
fields := strings.Split(scanner.Text(), " ")
|
||||
if len(fields) != 3 {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(fields[0], host) {
|
||||
var err error
|
||||
hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalf("error parsing %q: %v", fields[2], err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU=
|
||||
hostKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte("9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU="))
|
||||
log.Log(SSH, "hostkey err =", err)
|
||||
log.Log(SSH, "hostkey =", hostKey)
|
||||
if hostKey == nil {
|
||||
log.Log(SSH, "no hostkey found err =", err)
|
||||
log.Fatalf("no hostkey found for %s", host)
|
||||
}
|
||||
|
||||
return hostKey
|
||||
}
|
||||
*/
|
Loading…
Reference in New Issue