sshw

package module
v1.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 14, 2020 License: MIT Imports: 32 Imported by: 0

README

sshw

Build Status

ssh client wrapper for automatic login.

usage

install

use go get

go get -u github.com/ljun2016060/sshw/cmd/sshw

or download binary from releases.

upgrade

show latest version

sshw latest

upgrade sshw

sshw upgrade

config

put config file in ~/.sshw or ~/.sshw.yml or ~/.sshw.yaml or ./.sshw or ./.sshw.yml or ./.sshw.yaml. or sshw -f ./.sshw.yaml to set filename. With alias sshw -f ./.sshw.yaml dev

config example:
- { name: dev server fully configured, user: appuser, host: 192.168.8.35, port: 22, password: 123456 }
- { name: dev server with key path, user: appuser, host: 192.168.8.35, port: 22, keypath: /root/.ssh/id_rsa }
- { name: dev server with passphrase key, user: appuser, host: 192.168.8.35, port: 22, keypath: /root/.ssh/id_rsa, passphrase: abcdefghijklmn}
- { name: dev server without port, user: appuser, host: 192.168.8.35 }
- { name: dev server without user, host: 192.168.8.35 }
- { name: dev server without password, host: 192.168.8.35 }
- { name: ⚡️ server with emoji name, host: 192.168.8.35 }
- { name: server with alias, alias: dev, host: 192.168.8.35 }
- name: server with jump
  user: appuser
  host: 192.168.8.35
  port: 22
  password: 123456
  jump:
  - user: appuser
    host: 192.168.8.36
    port: 2222


# server group 1
- name: server group 1
  children:
  - { name: server 1, user: root, host: 192.168.1.2 }
  - { name: server 2, user: root, host: 192.168.1.3 }
  - { name: server 3, user: root, host: 192.168.1.4 }

# server group 2
- name: server group 2
  children:
  - { name: server 1, user: root, host: 192.168.2.2 }
  - { name: server 2, user: root, host: 192.168.3.3 }
  - { name: server 3, user: root, host: 192.168.4.4 }

reserved parameter

$USER is used to get user

Usage:

- { name: dev server fully configured, user: $USER, host: 192.168.8.35 }

sshw will use current-user to ssh server

callback

callback-shells is used to run command after ssh open a session. error-pattern is regex pattern that can be used to match message of error, it will return error if match successfully, but sshw receive output async, so if it could not match successfully, you can try wait some time.

delay mean before cmd, 'wait' mean after cmd

- name: dev server fully configured
  user: appuser
  host: 192.168.8.35
  port: 22
  password: 123456
  callback-shells:
  - {cmd: 2, error-pattern: 'No such file'}
  - {delay: 1500, cmd: 0}
  - {cmd: 'echo 1'}
  - {cmd: 'exit 1', wait: 1000}

ssh-agent

Support ssh-agent

Usage:

Add private to keychain

ssh-add ~/.ssh/.id_rsa

When jumper does not support channel, and you has no permission to modify /etc/ssh/ssh_config,or you won't save your private id_rsa in jumper. sshw will connect to jumper by ssh-agent.

- name: dev server fully configured
  user: appuser
  host: 192.168.8.35
  callback-shells:
  - {cmd: 'ssh 192.168.8.36'}

copy file

Callback support cp file to remote from local, it will convert src file to hex, and echo to target path

- name: dev server fully configured
  user: appuser
  host: 192.168.8.35
  callback-shells:
  - { cp: { src: '~/test.txt', tgt: '/tmp/test.txt' } }

execs

Run command before ssh dial or after cancel ssh dial. execs-pre is before dial. execs-stop is after cancel ssh, but it's important to note that execs-stop only run in host does exist.

If only needs to run command.

- name: command-checklist
  execs-pre:
  - cmd: "echo command-checklist"
  - cmd: "something else" 

If run command after cancel ssh.

- name: tell-some
  host: localhost
  callback-shells:
  - {cmd: 'echo login localhost'}
  - {cmd: 'exit 0'}
  execs-stop:
  - cmd: 'echo exit ssh'

template

Environment variable could be read if the value is string, use ${param1,param2:defaultValue}, it would be rendered by any one which is not empty value of param1 param2. Support escape, read as literal ${foo} if use \${foo}.

- name: ${name}
  execs-pre:
  - {cmd: 'echo ${content} localhost'}

merge

Merge config A to B.Only compare name and do override, otherwise it is complex.Also can use -f to specify persistent config.

sshw merge ./other.yaml

If doesn't want a name to be merge, use merge-ignore: true

- name: foo
  merge-ignore: true

Documentation

Index

Constants

View Source
const (
	TypeStr   = "str"
	TypeParam = "param"
)
View Source
const (
	ApplicationName = "sshw"
)

Variables

View Source
var (
	DefaultCiphers = []string{
		"aes128-ctr",
		"aes192-ctr",
		"aes256-ctr",
		"aes128-gcm@openssh.com",
		"chacha20-poly1305@openssh.com",
		"arcfour256",
		"arcfour128",
		"arcfour",
		"aes128-cbc",
		"3des-cbc",
		"blowfish-cbc",
		"cast128-cbc",
		"aes192-cbc",
		"aes256-cbc",
	}
)
View Source
var (
	ErrorInterrupt = errors.New("interrupt")
)

Functions

func ExtractBinary added in v1.5.0

func ExtractBinary(name string, needClose bool) (*os.File, error)

func LoadConfigBytes added in v1.2.0

func LoadConfigBytes(names ...string) (string, []byte, error)

func MergeNodes added in v1.6.0

func MergeNodes(dstPtr *[]*Node, src []*Node)

merge srcNode to dstNode only compare name and override, otherwise it is complex.

func PrepareConfig added in v1.4.0

func PrepareConfig(config []*Node) error

func RegisterLifecycle added in v1.2.0

func RegisterLifecycle(lifecycle Lifecycle)

func SetLogger

func SetLogger(logger Logger)

func WalkInterface added in v1.4.0

func WalkInterface(v reflect.Value, walked bool, solver ValueSolver) error

Types

type Client added in v1.0.3

type Client interface {
	Login() error
}

func NewClient added in v1.0.3

func NewClient(node *Node) Client

type CommonLifecycle added in v1.2.0

type CommonLifecycle struct {
	Name                     string
	PriorityFunc             func() int
	PostInitClientConfigFunc func(node *Node, clientConfig *ssh.ClientConfig) error
	PostSSHDialFunc          func(node *Node, client *ssh.Client) error
	PostNewSessionFunc       func(node *Node, session *ssh.Session) error
	PostShellFunc            func(node *Node, stdin io.WriteCloser) error
	OnStdoutFunc             func(node *Node, line []byte) error
	OnStderrFunc             func(node *Node, line []byte) error
	PostSessionWaitFunc      func(node *Node) error
}

CommonLifecycle is used to build Lifecycle quickly

func (*CommonLifecycle) OnStderr added in v1.2.0

func (d *CommonLifecycle) OnStderr(node *Node, line []byte) error

func (*CommonLifecycle) OnStdout added in v1.2.0

func (d *CommonLifecycle) OnStdout(node *Node, line []byte) error

func (*CommonLifecycle) PostInitClientConfig added in v1.2.0

func (d *CommonLifecycle) PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

func (*CommonLifecycle) PostNewSession added in v1.2.0

func (d *CommonLifecycle) PostNewSession(node *Node, session *ssh.Session) error

func (*CommonLifecycle) PostSSHDial added in v1.2.0

func (d *CommonLifecycle) PostSSHDial(node *Node, client *ssh.Client) error

func (*CommonLifecycle) PostSessionWait added in v1.2.0

func (d *CommonLifecycle) PostSessionWait(node *Node) error

func (*CommonLifecycle) PostShell added in v1.2.0

func (d *CommonLifecycle) PostShell(node *Node, stdin io.WriteCloser) error

func (*CommonLifecycle) Priority added in v1.2.0

func (d *CommonLifecycle) Priority() int

type CustomTemplate added in v1.4.0

type CustomTemplate struct {
	Templates []*TemplateNode
}

func ParseSshwTemplate added in v1.4.0

func ParseSshwTemplate(src string) *CustomTemplate

Parse string to Template For example: INPUT: ParseSshwTemplate("Foo${foo:a}bar") OUTPUT: []{{Type: TypeStr, Value: "Foo"}, {Type: TypeParam}, Value: "${foo:a}"}, {Type: TypeStr, Value: "bar"}}

func (*CustomTemplate) Execute added in v1.4.0

func (c *CustomTemplate) Execute() string

type GithubRepository added in v1.5.0

type GithubRepository struct {
	Url      string
	Username string
	Name     string
}

func (*GithubRepository) Download added in v1.5.0

func (g *GithubRepository) Download(versionMeta *VersionMeta) (*os.File, error)

Using version and filename to generate a remote url that is used to download file. Download it to file tmp. Then backup original file and replace it with Downloaded file.

func (*GithubRepository) LatestVersion added in v1.5.0

func (g *GithubRepository) LatestVersion() (*VersionMeta, error)

type Lifecycle added in v1.2.0

type Lifecycle interface {
	PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

	PostSSHDial(node *Node, client *ssh.Client) error

	PostNewSession(node *Node, session *ssh.Session) error

	PostShell(node *Node, stdin io.WriteCloser) error

	OnStdout(node *Node, line []byte) error

	OnStderr(node *Node, line []byte) error

	PostSessionWait(node *Node) error

	Priority() int
}

type LifecycleAgent added in v1.2.0

type LifecycleAgent struct {
	// contains filtered or unexported fields
}

func (*LifecycleAgent) PostInitClientConfig added in v1.2.0

func (l *LifecycleAgent) PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

func (*LifecycleAgent) PostNewSession added in v1.2.0

func (l *LifecycleAgent) PostNewSession(node *Node, session *ssh.Session) error

func (*LifecycleAgent) PostSSHDial added in v1.2.0

func (l *LifecycleAgent) PostSSHDial(node *Node, client *ssh.Client) error

func (*LifecycleAgent) Priority added in v1.2.0

func (l *LifecycleAgent) Priority() int

type LifecycleCallback added in v1.2.0

type LifecycleCallback struct {
	IsError bool
	Index   int
	Mutex   *sync.Mutex
	Cond    *sync.Cond
}

func (*LifecycleCallback) OnStdout added in v1.2.0

func (l *LifecycleCallback) OnStdout(node *Node, line []byte) error

func (*LifecycleCallback) PostShell added in v1.2.0

func (l *LifecycleCallback) PostShell(node *Node, stdin io.WriteCloser) error

type LifecycleComposite added in v1.2.0

type LifecycleComposite struct {
	// contains filtered or unexported fields
}

func (*LifecycleComposite) OnStderr added in v1.2.0

func (l *LifecycleComposite) OnStderr(node *Node, line []byte) error

func (*LifecycleComposite) OnStdout added in v1.2.0

func (l *LifecycleComposite) OnStdout(node *Node, line []byte) error

func (*LifecycleComposite) PostInitClientConfig added in v1.2.0

func (l *LifecycleComposite) PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

func (*LifecycleComposite) PostNewSession added in v1.2.0

func (l *LifecycleComposite) PostNewSession(node *Node, session *ssh.Session) error

func (*LifecycleComposite) PostSSHDial added in v1.2.0

func (l *LifecycleComposite) PostSSHDial(node *Node, client *ssh.Client) error

func (*LifecycleComposite) PostSessionWait added in v1.2.0

func (l *LifecycleComposite) PostSessionWait(node *Node) error

func (*LifecycleComposite) PostShell added in v1.2.0

func (l *LifecycleComposite) PostShell(node *Node, stdin io.WriteCloser) error

func (*LifecycleComposite) Priority added in v1.2.0

func (l *LifecycleComposite) Priority() int

type LifecycleIO added in v1.2.0

type LifecycleIO struct {
}

func (*LifecycleIO) OnStderr added in v1.2.0

func (*LifecycleIO) OnStderr(node *Node, bytes []byte) error

func (*LifecycleIO) OnStdout added in v1.2.0

func (*LifecycleIO) OnStdout(node *Node, bytes []byte) error

func (*LifecycleIO) Priority added in v1.2.0

func (*LifecycleIO) Priority() int

type LifecyclePassword added in v1.2.0

type LifecyclePassword struct {
}

func (*LifecyclePassword) PostInitClientConfig added in v1.2.0

func (*LifecyclePassword) PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

type LifecyclePem added in v1.2.0

type LifecyclePem struct {
}

func (*LifecyclePem) PostInitClientConfig added in v1.2.0

func (*LifecyclePem) PostInitClientConfig(node *Node, clientConfig *ssh.ClientConfig) error

type LifecycleQueue added in v1.2.0

type LifecycleQueue []Lifecycle

func (*LifecycleQueue) Len added in v1.2.0

func (l *LifecycleQueue) Len() int

func (*LifecycleQueue) Less added in v1.2.0

func (l *LifecycleQueue) Less(i, j int) bool

func (*LifecycleQueue) Pop added in v1.2.0

func (l *LifecycleQueue) Pop() interface{}

func (*LifecycleQueue) Push added in v1.2.0

func (l *LifecycleQueue) Push(x interface{})

func (*LifecycleQueue) Swap added in v1.2.0

func (l *LifecycleQueue) Swap(i, j int)

type LifecycleTerminal added in v1.2.0

type LifecycleTerminal struct {
	Callback func()
	// contains filtered or unexported fields
}

func (*LifecycleTerminal) PostNewSession added in v1.2.0

func (l *LifecycleTerminal) PostNewSession(node *Node, session *ssh.Session) error

func (*LifecycleTerminal) PostSessionWait added in v1.2.0

func (l *LifecycleTerminal) PostSessionWait(node *Node) error

func (*LifecycleTerminal) PostShell added in v1.2.0

func (l *LifecycleTerminal) PostShell(node *Node, stdin io.WriteCloser) error

func (*LifecycleTerminal) Priority added in v1.2.0

func (*LifecycleTerminal) Priority() int

type Logger

type Logger interface {
	Info(args ...interface{})
	Infof(format string, args ...interface{})
	Error(args ...interface{})
	Errorf(format string, args ...interface{})
}

func GetLogger

func GetLogger() Logger

type Node

type Node struct {
	Name           string               `yaml:"name"`
	Alias          string               `yaml:"alias,omitempty"`
	ExecsPre       []*NodeExec          `yaml:"execs-pre,omitempty"`
	ExecsStop      []*NodeExec          `yaml:"execs-stop,omitempty"`
	Host           string               `yaml:"host,omitempty"`
	User           string               `yaml:"user,omitempty"`
	Port           int                  `yaml:"port,omitempty"`
	KeyPath        string               `yaml:"keypath,omitempty"`
	Passphrase     string               `yaml:"passphrase,omitempty"`
	Password       string               `yaml:"password,omitempty"`
	CallbackShells []*NodeCallbackShell `yaml:"callback-shells,omitempty"`
	Children       []*Node              `yaml:"children,omitempty"`
	Jump           []*Node              `yaml:"jump,omitempty"`
	MergeIgnore    bool                 `yaml:"merge-ignore,omitempty"`
}

func LoadSshConfig added in v1.2.0

func LoadSshConfig() ([]*Node, error)

func LoadYamlConfig added in v1.4.0

func LoadYamlConfig(filename string) (string, []*Node, error)

func (*Node) String

func (n *Node) String() string

type NodeCallbackShell added in v1.3.0

type NodeCallbackShell struct {
	Cmd          string        `yaml:"cmd"`
	CpShell      NodeCp        `yaml:"cp,omitempty"`
	Delay        time.Duration `yaml:"delay,omitempty"`
	ErrorPattern string        `yaml:"error-pattern,omitempty"`
	Wait         time.Duration `yaml:"wait,omitempty"`
}

type NodeCp added in v1.3.0

type NodeCp struct {
	Src string `yaml:"src"`
	Tgt string `yaml:"tgt"`
}

type NodeExec added in v1.3.0

type NodeExec struct {
	Cmd string `yaml:"cmd"`
}

type Repository added in v1.5.0

type Repository interface {
	// get remote version
	LatestVersion() (*VersionMeta, error)

	// download remote file to specified path
	Download(versionMeta *VersionMeta) (*os.File, error)
}

type RuntimeSystem added in v1.5.0

type RuntimeSystem struct {
	GOOS        string
	GOOSAlias   string
	GOARCH      string
	GOARCHAlias string
}

type TemplateNode added in v1.4.0

type TemplateNode struct {
	Type  string
	Value string
}

func NewParamNode added in v1.4.0

func NewParamNode(v string) *TemplateNode

func NewStrNode added in v1.4.0

func NewStrNode(v string) *TemplateNode

type ValueSolver added in v1.4.0

type ValueSolver func(k string, t reflect.Type, v reflect.Value)

type VersionMeta added in v1.5.0

type VersionMeta struct {
	// version
	// e.t. v1.4.1
	Version string

	// file suffix
	// e.t. sshw-v1.4.1-darwin-osx-amd64.zip
	Filename string
}

type WriteCounter added in v1.5.0

type WriteCounter struct {
	Total            uint64
	ProgressTemplate string
}

WriteCounter counts the number of bytes written to it. It implements to the io.Writer interface and we can pass this into io.TeeReader() which will report progress on each write cycle.

func NewWriteCounter added in v1.5.0

func NewWriteCounter() *WriteCounter

func (WriteCounter) PrintProgress added in v1.5.0

func (wc WriteCounter) PrintProgress()

func (*WriteCounter) Write added in v1.5.0

func (wc *WriteCounter) Write(p []byte) (int, error)

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL