README

CircleCI

This package is an implementation of Expect in Go.

Features:

  • Spawning and controlling local processes with real PTYs.
  • Native SSH spawner.
  • Expect backed spawner for testing.
  • Generic spawner to make implementing additional Spawners simple.
  • Has a batcher for implementing workflows without having to write extra logic and code.

Options

All Spawn functions accept a variadic of type expect.Option , these are used for changing options of the Expecter.

CheckDuration

The Go Expecter checks for new data every two seconds as default. This can be changed by using the CheckDuration func CheckDuration(d time.Duration) Option.

Verbose

The Verbose option is used to turn on/off verbose logging for Expect/Send statements. This option can be very useful when troubleshooting workflows since it will log every interaction with the device.

VerboseWriter

The VerboseWriter option can be used to change where the verbose session logs are written. Using this option will start writing verbose output to the provided io.Writer instead of the log default.

See the ExampleVerbose code for an example of how to use this.

NoCheck

The Go Expecter periodically checks that the spawned process/ssh/session/telnet etc. session is alive. This option turns that check off.

DebugCheck

The DebugCheck option adds debugging to the alive Check done by the Expecter, this will start logging information every time the check is run. Can be used for troubleshooting and debugging of Spawners.

ChangeCheck

The ChangeCheck option makes it possible to replace the Spawner Check function with a brand new one.

SendTimeout

The SendTimeout set timeout on the Send command, without timeout the Send command will wait forewer for the expecter process.

Basic Examples

networkbit.ch

An article with some examples was written about goexpect on networkbit.ch.

The Wikipedia Expect examples.

Telnet

First we try to replicate the Telnet example from wikipedia as close as possible.

Interaction:

+ username:
- user\n
+ password:
- pass\n
+ %
- cmd\n
+ %
- exit\n

Error checking was omitted to keep the example short

package main

import (
	"flag"
	"fmt"
	"log"
	"regexp"
	"time"

	"github.com/google/goexpect"
	"github.com/google/goterm/term"
)

const (
	timeout = 10 * time.Minute
)

var (
	addr = flag.String("address", "", "address of telnet server")
	user = flag.String("user", "", "username to use")
	pass = flag.String("pass", "", "password to use")
	cmd  = flag.String("cmd", "", "command to run")

	userRE   = regexp.MustCompile("username:")
	passRE   = regexp.MustCompile("password:")
	promptRE = regexp.MustCompile("%")
)

func main() {
	flag.Parse()
	fmt.Println(term.Bluef("Telnet 1 example"))

	e, _, err := expect.Spawn(fmt.Sprintf("telnet %s", *addr), -1)
	if err != nil {
		log.Fatal(err)
	}
	defer e.Close()

	e.Expect(userRE, timeout)
	e.Send(*user + "\n")
	e.Expect(passRE, timeout)
	e.Send(*pass + "\n")
	e.Expect(promptRE, timeout)
	e.Send(*cmd + "\n")
	result, _, _ := e.Expect(promptRE, timeout)
	e.Send("exit\n")

	fmt.Println(term.Greenf("%s: result: %s\n", *cmd, result))
}

In essence to run and attach to a process the expect.Spawn(<cmd>,<timeout>) is used. The spawn returns an Expecter e that can run e.Expect and e.Send commands to match information in the output and Send information in.

See the https://github.com/google/goexpect/blob/master/examples/newspawner/telnet.go example for a slightly more fleshed out version

FTP

For the FTP example we use the expect.Batch for the following interaction.

+ username:
- user\n
+ password:
- pass\n
+ ftp>
- prompt\n
+ ftp>
- mget *\n
+ ftp>'
- bye\n

ftp_example.go

package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/google/goexpect"
	"github.com/google/goterm/term"
)

const (
	timeout = 10 * time.Minute
)

var (
	addr = flag.String("address", "", "address of telnet server")
	user = flag.String("user", "", "username to use")
	pass = flag.String("pass", "", "password to use")
)

func main() {
	flag.Parse()
	fmt.Println(term.Bluef("Ftp 1 example"))

	e, _, err := expect.Spawn(fmt.Sprintf("ftp %s", *addr), -1)
	if err != nil {
		log.Fatal(err)
	}
	defer e.Close()

	e.ExpectBatch([]expect.Batcher{
		&expect.BExp{R: "username:"},
		&expect.BSnd{S: *user + "\n"},
		&expect.BExp{R: "password:"},
		&expect.BSnd{S: *pass + "\n"},
		&expect.BExp{R: "ftp>"},
		&expect.BSnd{S: "bin\n"},
		&expect.BExp{R: "ftp>"},
		&expect.BSnd{S: "prompt\n"},
		&expect.BExp{R: "ftp>"},
		&expect.BSnd{S: "mget *\n"},
		&expect.BExp{R: "ftp>"},
		&expect.BSnd{S: "bye\n"},
	}, timeout)

	fmt.Println(term.Greenf("All done"))
}

Using the expect.Batcher makes the standard Send/Expect interactions more compact and simpler to write.

SSH

With the SSH login example we test out the expect.Caser and the Case Tags.

Also for this we'll use the Go Expect native SSH Spawner instead of spawning a process.

Interaction:

+ "Login: "
- user
+ "Password: "
- pass1
+ "Wrong password"
+ "Login"
- user
+ "Password: "
- pass2
+ router#

ssh_example.go

package main

import (
	"flag"
	"fmt"
	"log"
	"regexp"
	"time"

	"golang.org/x/crypto/ssh"

	"google.golang.org/grpc/codes"

	"github.com/google/goexpect"
	"github.com/google/goterm/term"
)

const (
	timeout = 10 * time.Minute
)

var (
	addr  = flag.String("address", "", "address of telnet server")
	user  = flag.String("user", "user", "username to use")
	pass1 = flag.String("pass1", "pass1", "password to use")
	pass2 = flag.String("pass2", "pass2", "alternate password to use")
)

func main() {
	flag.Parse()
	fmt.Println(term.Bluef("SSH Example"))

	sshClt, err := ssh.Dial("tcp", *addr, &ssh.ClientConfig{
		User:            *user,
		Auth:            []ssh.AuthMethod{ssh.Password(*pass1)},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	})
	if err != nil {
		log.Fatalf("ssh.Dial(%q) failed: %v", *addr, err)
	}
	defer sshClt.Close()

	e, _, err := expect.SpawnSSH(sshClt, timeout)
	if err != nil {
		log.Fatal(err)
	}
	defer e.Close()

	e.ExpectBatch([]expect.Batcher{
		&expect.BCas{[]expect.Caser{
			&expect.Case{R: regexp.MustCompile(`router#`), T: expect.OK()},
			&expect.Case{R: regexp.MustCompile(`Login: `), S: *user,
				T: expect.Continue(expect.NewStatus(codes.PermissionDenied, "wrong username")), Rt: 3},
			&expect.Case{R: regexp.MustCompile(`Password: `), S: *pass1, T: expect.Next(), Rt: 1},
			&expect.Case{R: regexp.MustCompile(`Password: `), S: *pass2,
				T: expect.Continue(expect.NewStatus(codes.PermissionDenied, "wrong password")), Rt: 1},
		}},
	}, timeout)

	fmt.Println(term.Greenf("All done"))
}

Generic Spawner

The Go Expect package supports adding new Spawners with the func SpawnGeneric(opt *GenOptions, timeout time.Duration, opts ...Option) (*GExpect, <-chan error, error) function.

telnet spawner

From the newspawner example.

func telnetSpawn(addr string, timeout time.Duration, opts ...expect.Option) (expect.Expecter, <-chan error, error) {
	conn, err := telnet.Dial(network, addr)
	if err != nil {
		return nil, nil, err
	}

	resCh := make(chan error)

	return expect.SpawnGeneric(&expect.GenOptions{
		In:  conn,
		Out: conn,
		Wait: func() error {
			return <-resCh
		},
		Close: func() error {
			close(resCh)
			return conn.Close()
		},
		Check: func() bool { return true },
	}, timeout, opts...)
}

Fake Spawner

The Go Expect package includes a Fake Spawner func SpawnFake(b []Batcher, timeout time.Duration, opt ...Option) (*GExpect, <-chan error, error). This is expected to be used to simplify testing and faking of interactive workflows.

Fake Spawner

// TestExpect tests the Expect function.
func TestExpect(t *testing.T) {
	tests := []struct {
		name    string
		fail    bool
		srv     []Batcher
		timeout time.Duration
		re      *regexp.Regexp
	}{{
		name: "Match prompt",
		srv: []Batcher{
			&BSnd{`
Pretty please don't hack my chassis

router1> `},
		},
		re:      regexp.MustCompile("router1>"),
		timeout: 2 * time.Second,
	}, {
		name: "Match fail",
		fail: true,
		re:   regexp.MustCompile("router1>"),
		srv: []Batcher{
			&BSnd{`
Welcome

Router42>`},
		},
		timeout: 1 * time.Second,
	}}

	for _, tst := range tests {
		exp, _, err := SpawnFake(tst.srv, tst.timeout)
		if err != nil {
			if !tst.fail {
				t.Errorf("%s: SpawnFake failed: %v", tst.name, err)
			}
			continue
		}
		out, _, err := exp.Expect(tst.re, tst.timeout)
		if got, want := err != nil, tst.fail; got != want {
			t.Errorf("%s: Expect(%q,%v) = %t want: %t , err: %v, out: %q", tst.name, tst.re.String(), tst.timeout, got, want, err, out)
			continue
		}
	}
}

Disclaimer: This is not an official Google product.

Expand ▾ Collapse ▴

Documentation

Overview

    Package expect is a Go version of the classic TCL Expect.

    Index

    Examples

    Constants

    View Source
    const (
    	// BatchSend for invoking Send in a batch
    	BatchSend = iota
    	// BatchExpect for invoking Expect in a batch
    	BatchExpect
    	// BatchSwitchCase for invoking ExpectSwitchCase in a batch
    	BatchSwitchCase
    	// BatchSendSignal for invoking SendSignal in a batch.
    	BatchSendSignal
    )

      BatchCommands.

      View Source
      const (
      	// OKTag marks the desired state was reached.
      	OKTag = Tag(iota)
      	// FailTag means reaching this state will fail the Switch/Case.
      	FailTag
      	// ContinueTag will recheck for matches.
      	ContinueTag
      	// NextTag skips match and continues to the next one.
      	NextTag
      	// NoTag signals no tag was set for this case.
      	NoTag
      )
      View Source
      const DefaultTimeout = 60 * time.Second

        DefaultTimeout is the default Expect timeout.

        Variables

        This section is empty.

        Functions

        func Continue

        func Continue(s *Status) func() (Tag, *Status)

          Continue returns the Continue Tag and status.

          func Fail

          func Fail(s *Status) func() (Tag, *Status)

            Fail returns Fail Tag and status.

            func LogContinue

            func LogContinue(msg string, s *Status) func() (Tag, *Status)

              LogContinue logs the message and returns the Continue Tag and status.

              func Next

              func Next() func() (Tag, *Status)

                Next returns the Next Tag and status.

                func OK

                func OK() func() (Tag, *Status)

                  OK returns the OK Tag and status.

                  Types

                  type BCas

                  type BCas struct {
                  	// C holds the Caser array for the SwitchCase command.
                  	C []Caser
                  }

                    BCas implements the Batcher interface for SwitchCase commands.

                    func (*BCas) Arg

                    func (bc *BCas) Arg() string

                      Arg returns an empty string , not used for SwitchCase.

                      func (*BCas) Cases

                      func (bc *BCas) Cases() []Caser

                        Cases returns the Caser structure.

                        func (*BCas) Cmd

                        func (bc *BCas) Cmd() int

                          Cmd returns the SwitchCase command(BatchSwitchCase).

                          func (*BCas) Timeout

                          func (bc *BCas) Timeout() time.Duration

                            Timeout returns -1 , setting it to the default value.

                            type BCasT

                            type BCasT struct {
                            	// Cs holds the Caser array for the SwitchCase command.
                            	C []Caser
                            	// Tout holds the SwitchCase timeout in seconds.
                            	T int
                            }

                              BCasT implements the Batcher interfacs for SwitchCase commands, adding a timeout option to the BCas type.

                              func (*BCasT) Arg

                              func (bct *BCasT) Arg() string

                                Arg returns an empty string , not used for SwitchCase.

                                func (*BCasT) Cases

                                func (bct *BCasT) Cases() []Caser

                                  Cases returns the Caser structure.

                                  func (*BCasT) Cmd

                                  func (bct *BCasT) Cmd() int

                                    Cmd returns the SwitchCase command(BatchSwitchCase).

                                    func (*BCasT) Timeout

                                    func (bct *BCasT) Timeout() time.Duration

                                      Timeout returns the timeout in seconds.

                                      type BCase

                                      type BCase struct {
                                      	// R contains the string regular expression.
                                      	R string
                                      	// S contains the string to be sent if R matches.
                                      	S string
                                      	// T contains the Tag.
                                      	T func() (Tag, *Status)
                                      	// Rt contains the number of retries.
                                      	Rt int
                                      }

                                        BCase with just a string is a bit more friendly to scripting. Implements the Caser interface.

                                        func (*BCase) RE

                                        func (b *BCase) RE() (*regexp.Regexp, error)

                                          RE returns the compiled regular expression.

                                          func (*BCase) Retry

                                          func (b *BCase) Retry() bool

                                            Retry decrements the Retry counter and checks if there are any retries left.

                                            func (*BCase) String

                                            func (b *BCase) String() string

                                              Send returns the string to send.

                                              func (*BCase) Tag

                                              func (b *BCase) Tag() (Tag, *Status)

                                                Tag returns the BCase Tag.

                                                type BExp

                                                type BExp struct {
                                                	// R contains the Expect command regular expression.
                                                	R string
                                                }

                                                  BExp implements the Batcher interface for Expect commands using the default timeout.

                                                  func (*BExp) Arg

                                                  func (be *BExp) Arg() string

                                                    Arg returns the Expect regular expression.

                                                    func (*BExp) Cases

                                                    func (be *BExp) Cases() []Caser

                                                      Cases always returns nil for the Expect command.

                                                      func (*BExp) Cmd

                                                      func (be *BExp) Cmd() int

                                                        Cmd returns the Expect command (BatchExpect).

                                                        func (*BExp) Timeout

                                                        func (be *BExp) Timeout() time.Duration

                                                          Timeout always returns -1 which sets it to the value used to call the ExpectBatch function.

                                                          type BExpT

                                                          type BExpT struct {
                                                          	// R contains the Expect command regular expression.
                                                          	R string
                                                          	// T holds the Expect command timeout in seconds.
                                                          	T int
                                                          }

                                                            BExpT implements the Batcher interface for Expect commands adding a timeout option to the BExp type.

                                                            func (*BExpT) Arg

                                                            func (bt *BExpT) Arg() string

                                                              Arg returns the Expect regular expression.

                                                              func (*BExpT) Cases

                                                              func (bt *BExpT) Cases() []Caser

                                                                Cases always return nil for the Expect command.

                                                                func (*BExpT) Cmd

                                                                func (bt *BExpT) Cmd() int

                                                                  Cmd returns the Expect command (BatchExpect).

                                                                  func (*BExpT) Timeout

                                                                  func (bt *BExpT) Timeout() time.Duration

                                                                    Timeout returns the timeout in seconds.

                                                                    type BSig

                                                                    type BSig struct {
                                                                    	// S contains the signal.
                                                                    	S syscall.Signal
                                                                    }

                                                                      BSig implements the Batcher interface for SendSignal commands.

                                                                      func (*BSig) Arg

                                                                      func (bs *BSig) Arg() string

                                                                        Arg returns the signal integer.

                                                                        func (*BSig) Cases

                                                                        func (bs *BSig) Cases() []Caser

                                                                          Cases always returns nil for BSig.

                                                                          func (*BSig) Cmd

                                                                          func (bs *BSig) Cmd() int

                                                                            Cmd returns the SendSignal command (BatchSendSignal).

                                                                            func (*BSig) Timeout

                                                                            func (bs *BSig) Timeout() time.Duration

                                                                              Timeout always returns 0 for BSig.

                                                                              type BSnd

                                                                              type BSnd struct {
                                                                              	S string
                                                                              }

                                                                                BSnd implements the Batcher interface for Send commands.

                                                                                func (*BSnd) Arg

                                                                                func (bs *BSnd) Arg() string

                                                                                  Arg returns the data to be sent.

                                                                                  func (*BSnd) Cases

                                                                                  func (bs *BSnd) Cases() []Caser

                                                                                    Cases always returns nil , not used for Send commands.

                                                                                    func (*BSnd) Cmd

                                                                                    func (bs *BSnd) Cmd() int

                                                                                      Cmd returns the Send command(BatchSend).

                                                                                      func (*BSnd) Timeout

                                                                                      func (bs *BSnd) Timeout() time.Duration

                                                                                        Timeout always returns 0 , Send doesn't have a timeout.

                                                                                        type BatchRes

                                                                                        type BatchRes struct {
                                                                                        	// Idx is used to match the result with the []Batcher commands sent in.
                                                                                        	Idx int
                                                                                        	// Out output buffer for the expect command at Batcher[Idx].
                                                                                        	Output string
                                                                                        	// Match regexp matches for expect command at Batcher[Idx].
                                                                                        	Match []string
                                                                                        }

                                                                                          BatchRes returned from ExpectBatch for every Expect command executed.

                                                                                          type Batcher

                                                                                          type Batcher interface {
                                                                                          	// cmd returns the Batch command.
                                                                                          	Cmd() int
                                                                                          	// Arg returns the command argument.
                                                                                          	Arg() string
                                                                                          	// Timeout returns the timeout duration for the command , <0 gives default value.
                                                                                          	Timeout() time.Duration
                                                                                          	// Cases returns the Caser structure for SwitchCase commands.
                                                                                          	Cases() []Caser
                                                                                          }

                                                                                            Batcher interface is used to make it more straightforward and readable to create batches of Expects.

                                                                                            var batch = []Batcher{

                                                                                            &BExpT{"password",8},
                                                                                            &BSnd{"password\n"},
                                                                                            &BExp{"olakar@router>"},
                                                                                            &BSnd{ "show interface description\n"},
                                                                                            &BExp{ "olakar@router>"},
                                                                                            

                                                                                            }

                                                                                            var batchSwCaseReplace = []Batcher{

                                                                                            &BCasT{[]Caser{
                                                                                            	&BCase{`([0-9]) -- .*\(MASTER\)`, `\1` + "\n"}}, 1},
                                                                                            &BExp{`prompt/>`},
                                                                                            

                                                                                            }

                                                                                            type Case

                                                                                            type Case struct {
                                                                                            	// R is the compiled regexp to match.
                                                                                            	R *regexp.Regexp
                                                                                            	// S is the string to send if Regexp matches.
                                                                                            	S string
                                                                                            	// T is the Tag for this Case.
                                                                                            	T func() (Tag, *Status)
                                                                                            	// Rt specifies number of times to retry, only used for cases tagged with Continue.
                                                                                            	Rt int
                                                                                            }

                                                                                              Case used by the ExpectSwitchCase to take different Cases. Implements the Caser interface.

                                                                                              func (*Case) RE

                                                                                              func (c *Case) RE() (*regexp.Regexp, error)

                                                                                                RE returns the compiled regular expression.

                                                                                                func (*Case) Retry

                                                                                                func (c *Case) Retry() bool

                                                                                                  Retry decrements the Retry counter and checks if there are any retries left.

                                                                                                  func (*Case) String

                                                                                                  func (c *Case) String() string

                                                                                                    Send returns the string to send if regexp matches

                                                                                                    func (*Case) Tag

                                                                                                    func (c *Case) Tag() (Tag, *Status)

                                                                                                      Tag returns the tag for this case.

                                                                                                      type Caser

                                                                                                      type Caser interface {
                                                                                                      	// RE returns a compiled regexp
                                                                                                      	RE() (*regexp.Regexp, error)
                                                                                                      	// Send returns the send string
                                                                                                      	String() string
                                                                                                      	// Tag returns the Tag.
                                                                                                      	Tag() (Tag, *Status)
                                                                                                      	// Retry returns true if there are retries left.
                                                                                                      	Retry() bool
                                                                                                      }

                                                                                                        Caser is an interface for ExpectSwitchCase and Batch to be able to handle both the Case struct and the more script friendly BCase struct.

                                                                                                        type Expecter

                                                                                                        type Expecter interface {
                                                                                                        	// Expect reads output from a spawned session and tries matching it with the provided regular expression.
                                                                                                        	// It returns  all output found until match.
                                                                                                        	Expect(*regexp.Regexp, time.Duration) (string, []string, error)
                                                                                                        	// ExpectBatch takes an array of BatchEntries and runs through them in order. For every Expect
                                                                                                        	// command a BatchRes entry is created with output buffer and sub matches.
                                                                                                        	// Failure of any of the batch commands will stop the execution, returning the results up to the
                                                                                                        	// failure.
                                                                                                        	ExpectBatch([]Batcher, time.Duration) ([]BatchRes, error)
                                                                                                        	// ExpectSwitchCase makes it possible to Expect with multiple regular expressions and actions. Returns the
                                                                                                        	// full output and submatches of the commands together with an index for the matching Case.
                                                                                                        	ExpectSwitchCase([]Caser, time.Duration) (string, []string, int, error)
                                                                                                        	// Send sends data into the spawned session.
                                                                                                        	Send(string) error
                                                                                                        	// Close closes the spawned session and files.
                                                                                                        	Close() error
                                                                                                        }

                                                                                                          Expecter interface primarily to make testing easier.

                                                                                                          type GExpect

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

                                                                                                            GExpect implements the Expecter interface.

                                                                                                            func Spawn

                                                                                                            func Spawn(command string, timeout time.Duration, opts ...Option) (*GExpect, <-chan error, error)

                                                                                                              Spawn starts a new process and collects the output. The error channel returns the result of the command Spawned when it finishes. Arguments may not contain spaces.

                                                                                                              func SpawnFake

                                                                                                              func SpawnFake(b []Batcher, timeout time.Duration, opt ...Option) (*GExpect, <-chan error, error)

                                                                                                                SpawnFake spawns an expect.Batcher.

                                                                                                                func SpawnGeneric

                                                                                                                func SpawnGeneric(opt *GenOptions, timeout time.Duration, opts ...Option) (*GExpect, <-chan error, error)

                                                                                                                  SpawnGeneric is used to write generic Spawners. It returns an Expecter. The returned channel will give the return status of the spawned session, in practice this means the return value of the provided Wait function.

                                                                                                                  func SpawnSSH

                                                                                                                  func SpawnSSH(sshClient *ssh.Client, timeout time.Duration, opts ...Option) (*GExpect, <-chan error, error)

                                                                                                                    SpawnSSH starts an interactive SSH session,ties it to a PTY and collects the output. The returned channel sends the state of the SSH session after it finishes.

                                                                                                                    func SpawnSSHPTY

                                                                                                                    func SpawnSSHPTY(sshClient *ssh.Client, timeout time.Duration, term term.Termios, opts ...Option) (*GExpect, <-chan error, error)

                                                                                                                      SpawnSSHPTY starts an interactive SSH session and ties it to a local PTY, optionally requests a remote PTY.

                                                                                                                      func SpawnWithArgs

                                                                                                                      func SpawnWithArgs(command []string, timeout time.Duration, opts ...Option) (*GExpect, <-chan error, error)

                                                                                                                        SpawnWithArgs starts a new process and collects the output. The error channel returns the result of the command Spawned when it finishes. Arguments may contain spaces.

                                                                                                                        func (*GExpect) Close

                                                                                                                        func (e *GExpect) Close() error

                                                                                                                          Close closes the Spawned session.

                                                                                                                          func (*GExpect) Expect

                                                                                                                          func (e *GExpect) Expect(re *regexp.Regexp, timeout time.Duration) (string, []string, error)

                                                                                                                            Expect reads spawned processes output looking for input regular expression. Timeout set to 0 makes Expect return the current buffer. Negative timeout value sets it to Default timeout.

                                                                                                                            func (*GExpect) ExpectBatch

                                                                                                                            func (e *GExpect) ExpectBatch(batch []Batcher, timeout time.Duration) ([]BatchRes, error)

                                                                                                                              ExpectBatch takes an array of BatchEntry and executes them in order filling in the BatchRes array for any Expect command executed.

                                                                                                                              func (*GExpect) ExpectSwitchCase

                                                                                                                              func (e *GExpect) ExpectSwitchCase(cs []Caser, timeout time.Duration) (string, []string, int, error)

                                                                                                                                ExpectSwitchCase checks each Case against the accumulated out buffer, sending specified string back. Leaving Send empty will Send nothing to the process. Substring expansion can be used eg.

                                                                                                                                Case{`vf[0-9]{2}.[a-z]{3}[0-9]{2}\.net).*UP`,`show arp \1`}
                                                                                                                                Given: vf11.hnd01.net            UP      35 (4)        34 (4)          CONNECTED         0              0/0
                                                                                                                                Would send: show arp vf11.hnd01.net
                                                                                                                                

                                                                                                                                func (*GExpect) Options

                                                                                                                                func (e *GExpect) Options(opts ...Option) (prev Option)

                                                                                                                                  Options sets the specified options.

                                                                                                                                  func (*GExpect) Read

                                                                                                                                  func (e *GExpect) Read(p []byte) (nr int, err error)

                                                                                                                                    Read implements the reader interface for the out buffer.

                                                                                                                                    func (*GExpect) Send

                                                                                                                                    func (e *GExpect) Send(in string) error

                                                                                                                                      Send sends a string to spawned process.

                                                                                                                                      func (*GExpect) SendSignal

                                                                                                                                      func (e *GExpect) SendSignal(sig os.Signal) error

                                                                                                                                        SendSignal sends a signal to the Expect controlled process. Only works on Process Expecters.

                                                                                                                                        Example

                                                                                                                                          ExampleGExpect_SendSignal shows the usage of the SendSignal call.

                                                                                                                                          Code:

                                                                                                                                          exp, r, err := Spawn("testdata/traptest.sh", 30*time.Second)
                                                                                                                                          if err != nil {
                                                                                                                                          	fmt.Printf("Spawn failed: %v\n", err)
                                                                                                                                          	return
                                                                                                                                          }
                                                                                                                                          if match, buf, err := exp.Expect(signalsInstalled, time.Second*20); err != nil {
                                                                                                                                          	fmt.Printf("exp.Expect failed, match: %v, buf: %v, err: %v", match, buf, err)
                                                                                                                                          	return
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          if err := exp.SendSignal(syscall.SIGUSR1); err != nil {
                                                                                                                                          	fmt.Printf("exp.SendSignal failed: %v", err)
                                                                                                                                          	return
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          reExpect, err := regexp.Compile("USR1")
                                                                                                                                          if err != nil {
                                                                                                                                          	fmt.Printf("regexp.Compile(%q) failed: %v", "Sig USR1", err)
                                                                                                                                          	return
                                                                                                                                          }
                                                                                                                                          
                                                                                                                                          match, buf, err := exp.Expect(reExpect, time.Second*20)
                                                                                                                                          if err != nil {
                                                                                                                                          	fmt.Printf("exp.Expect failed, match: %v, buf: %v, err: %v", match, buf, err)
                                                                                                                                          	return
                                                                                                                                          }
                                                                                                                                          fmt.Println(match)
                                                                                                                                          <-r
                                                                                                                                          
                                                                                                                                          Got the USR1 Signal
                                                                                                                                          

                                                                                                                                          func (*GExpect) String

                                                                                                                                          func (e *GExpect) String() string

                                                                                                                                            String implements the stringer interface.

                                                                                                                                            type GenOptions

                                                                                                                                            type GenOptions struct {
                                                                                                                                            	// In is where Expect Send messages will be written.
                                                                                                                                            	In io.WriteCloser
                                                                                                                                            	// Out will be read and matched by the expecter.
                                                                                                                                            	Out io.Reader
                                                                                                                                            	// Wait is used by expect to know when the session is over and cleanup of io Go routines should happen.
                                                                                                                                            	Wait func() error
                                                                                                                                            	// Close will be called as part of the expect Close, should normally include a Close of the In WriteCloser.
                                                                                                                                            	Close func() error
                                                                                                                                            	// Check is called everytime a Send or Expect function is called to makes sure the session is still running.
                                                                                                                                            	Check func() bool
                                                                                                                                            }

                                                                                                                                              GenOptions contains the options needed to set up a generic Spawner.

                                                                                                                                              type Option

                                                                                                                                              type Option func(*GExpect) Option

                                                                                                                                                Option represents one Expecter option.

                                                                                                                                                func ChangeCheck

                                                                                                                                                func ChangeCheck(f func() bool) Option

                                                                                                                                                  ChangeCheck changes the Expect check function.

                                                                                                                                                  Example

                                                                                                                                                    ExampleChangeCheck changes the check function runtime for an Expect session.

                                                                                                                                                    Code:

                                                                                                                                                    rIn, wIn := io.Pipe()
                                                                                                                                                    rOut, wOut := io.Pipe()
                                                                                                                                                    waitCh := make(chan error)
                                                                                                                                                    outCh := make(chan string)
                                                                                                                                                    defer close(outCh)
                                                                                                                                                    
                                                                                                                                                    go fakeCli(cliMap, rIn, wOut)
                                                                                                                                                    go func() {
                                                                                                                                                    	var last string
                                                                                                                                                    	for s := range outCh {
                                                                                                                                                    		if s == last {
                                                                                                                                                    			continue
                                                                                                                                                    		}
                                                                                                                                                    		fmt.Println(s)
                                                                                                                                                    		last = s
                                                                                                                                                    	}
                                                                                                                                                    }()
                                                                                                                                                    
                                                                                                                                                    exp, r, err := SpawnGeneric(&GenOptions{
                                                                                                                                                    	In:    wIn,
                                                                                                                                                    	Out:   rOut,
                                                                                                                                                    	Wait:  func() error { return <-waitCh },
                                                                                                                                                    	Close: func() error { return wIn.Close() },
                                                                                                                                                    	Check: func() bool {
                                                                                                                                                    		outCh <- "Original check"
                                                                                                                                                    		return true
                                                                                                                                                    	}}, -1)
                                                                                                                                                    if err != nil {
                                                                                                                                                    	fmt.Printf("SpawnGeneric failed: %v\n", err)
                                                                                                                                                    	return
                                                                                                                                                    }
                                                                                                                                                    re := regexp.MustCompile("testrouter#")
                                                                                                                                                    interact := func() {
                                                                                                                                                    	for cmd := range cliMap {
                                                                                                                                                    		if err := exp.Send(cmd + "\n"); err != nil {
                                                                                                                                                    			fmt.Printf("exp.Send(%q) failed: %v\n", cmd+"\n", err)
                                                                                                                                                    			return
                                                                                                                                                    		}
                                                                                                                                                    		out, _, err := exp.Expect(re, -1)
                                                                                                                                                    		if err != nil {
                                                                                                                                                    			fmt.Printf("exp.Expect(%v) failed: %v out: %v", re, err, out)
                                                                                                                                                    			return
                                                                                                                                                    		}
                                                                                                                                                    	}
                                                                                                                                                    }
                                                                                                                                                    interact()
                                                                                                                                                    prev := exp.Options(ChangeCheck(func() bool {
                                                                                                                                                    	outCh <- "Replaced check"
                                                                                                                                                    	return true
                                                                                                                                                    }))
                                                                                                                                                    interact()
                                                                                                                                                    exp.Options(prev)
                                                                                                                                                    interact()
                                                                                                                                                    
                                                                                                                                                    waitCh <- nil
                                                                                                                                                    exp.Close()
                                                                                                                                                    wOut.Close()
                                                                                                                                                    
                                                                                                                                                    <-r
                                                                                                                                                    
                                                                                                                                                    Original check
                                                                                                                                                    Replaced check
                                                                                                                                                    Original check
                                                                                                                                                    

                                                                                                                                                    func CheckDuration

                                                                                                                                                    func CheckDuration(d time.Duration) Option

                                                                                                                                                      CheckDuration changes the default duration checking for new incoming data.

                                                                                                                                                      func DebugCheck

                                                                                                                                                      func DebugCheck(l *log.Logger) Option

                                                                                                                                                        DebugCheck adds logging to the check function. The check function for the spawners are called at creation/timeouts and I/O so can be usable for printing current state during debugging.

                                                                                                                                                        Example

                                                                                                                                                          ExampleDebugCheck toggles the DebugCheck option.

                                                                                                                                                          Code:

                                                                                                                                                          rIn, wIn := io.Pipe()
                                                                                                                                                          rOut, wOut := io.Pipe()
                                                                                                                                                          rLog, wLog := io.Pipe()
                                                                                                                                                          waitCh := make(chan error)
                                                                                                                                                          defer rIn.Close()
                                                                                                                                                          defer wOut.Close()
                                                                                                                                                          defer wLog.Close()
                                                                                                                                                          
                                                                                                                                                          go fakeCli(cliMap, rIn, wOut)
                                                                                                                                                          
                                                                                                                                                          exp, r, err := SpawnGeneric(&GenOptions{
                                                                                                                                                          	In:    wIn,
                                                                                                                                                          	Out:   rOut,
                                                                                                                                                          	Wait:  func() error { return <-waitCh },
                                                                                                                                                          	Close: func() error { return wIn.Close() },
                                                                                                                                                          	Check: func() bool {
                                                                                                                                                          		return true
                                                                                                                                                          	}}, -1)
                                                                                                                                                          if err != nil {
                                                                                                                                                          	log.Errorf("SpawnGeneric failed: %v", err)
                                                                                                                                                          	return
                                                                                                                                                          }
                                                                                                                                                          re := regexp.MustCompile("testrouter#")
                                                                                                                                                          interact := func() {
                                                                                                                                                          	for cmd := range cliMap {
                                                                                                                                                          		if err := exp.Send(cmd + "\n"); err != nil {
                                                                                                                                                          			log.Errorf("exp.Send(%q) failed: %v\n", cmd+"\n", err)
                                                                                                                                                          			return
                                                                                                                                                          		}
                                                                                                                                                          		out, _, err := exp.Expect(re, -1)
                                                                                                                                                          		if err != nil {
                                                                                                                                                          			log.Errorf("exp.Expect(%v) failed: %v out: %v", re, err, out)
                                                                                                                                                          			return
                                                                                                                                                          		}
                                                                                                                                                          	}
                                                                                                                                                          }
                                                                                                                                                          
                                                                                                                                                          go func() {
                                                                                                                                                          	var last string
                                                                                                                                                          	scn := bufio.NewScanner(rLog)
                                                                                                                                                          	for scn.Scan() {
                                                                                                                                                          		ws := strings.Split(scn.Text(), " ")
                                                                                                                                                          		if ws[0] == last {
                                                                                                                                                          			continue
                                                                                                                                                          		}
                                                                                                                                                          		last = ws[0]
                                                                                                                                                          		fmt.Println(ws[0])
                                                                                                                                                          	}
                                                                                                                                                          }()
                                                                                                                                                          
                                                                                                                                                          fmt.Println("First round")
                                                                                                                                                          interact()
                                                                                                                                                          fmt.Println("Second round - Debugging enabled")
                                                                                                                                                          prev := exp.Options(DebugCheck(stdlog.New(wLog, "DebugExample ", 0)))
                                                                                                                                                          interact()
                                                                                                                                                          exp.Options(prev)
                                                                                                                                                          fmt.Println("Last round - Previous Check put back")
                                                                                                                                                          interact()
                                                                                                                                                          
                                                                                                                                                          waitCh <- nil
                                                                                                                                                          exp.Close()
                                                                                                                                                          wOut.Close()
                                                                                                                                                          
                                                                                                                                                          <-r
                                                                                                                                                          
                                                                                                                                                          First round
                                                                                                                                                          Second round - Debugging enabled
                                                                                                                                                          DebugExample
                                                                                                                                                          Last round - Previous Check put back
                                                                                                                                                          

                                                                                                                                                          func NoCheck

                                                                                                                                                          func NoCheck() Option

                                                                                                                                                            NoCheck turns off the Expect alive checks.

                                                                                                                                                            func PartialMatch

                                                                                                                                                            func PartialMatch(v bool) Option

                                                                                                                                                              PartialMatch enables/disables the returning of unmatched buffer so that consecutive expect call works.

                                                                                                                                                              func SendTimeout

                                                                                                                                                              func SendTimeout(timeout time.Duration) Option

                                                                                                                                                                SendTimeout set timeout for Send commands

                                                                                                                                                                func SetEnv

                                                                                                                                                                func SetEnv(env []string) Option

                                                                                                                                                                  SetEnv sets the environmental variables of the spawned process.

                                                                                                                                                                  func SetSysProcAttr

                                                                                                                                                                  func SetSysProcAttr(args *syscall.SysProcAttr) Option

                                                                                                                                                                    SetSysProcAttr sets the SysProcAttr syscall values for the spawned process. Because this modifies cmd, it will only work with the process spawners and not effect the GExpect option method.

                                                                                                                                                                    func Tee

                                                                                                                                                                    func Tee(w io.WriteCloser) Option

                                                                                                                                                                      Tee duplicates all of the spawned process's output to the given writer and closes the writer when complete. Writes occur from another thread, so synchronization may be necessary.

                                                                                                                                                                      func Verbose

                                                                                                                                                                      func Verbose(v bool) Option

                                                                                                                                                                        Verbose enables/disables verbose logging of matches and sends.

                                                                                                                                                                        Example

                                                                                                                                                                          ExampleVerbose changes the Verbose and VerboseWriter options.

                                                                                                                                                                          Code:

                                                                                                                                                                          rIn, wIn := io.Pipe()
                                                                                                                                                                          rOut, wOut := io.Pipe()
                                                                                                                                                                          waitCh := make(chan error)
                                                                                                                                                                          outCh := make(chan string)
                                                                                                                                                                          defer close(outCh)
                                                                                                                                                                          
                                                                                                                                                                          go fakeCli(cliMap, rIn, wOut)
                                                                                                                                                                          go func() {
                                                                                                                                                                          	var last string
                                                                                                                                                                          	for s := range outCh {
                                                                                                                                                                          		if s == last {
                                                                                                                                                                          			continue
                                                                                                                                                                          		}
                                                                                                                                                                          		fmt.Println(s)
                                                                                                                                                                          		last = s
                                                                                                                                                                          	}
                                                                                                                                                                          }()
                                                                                                                                                                          
                                                                                                                                                                          exp, r, err := SpawnGeneric(&GenOptions{
                                                                                                                                                                          	In:    wIn,
                                                                                                                                                                          	Out:   rOut,
                                                                                                                                                                          	Wait:  func() error { return <-waitCh },
                                                                                                                                                                          	Close: func() error { return wIn.Close() },
                                                                                                                                                                          	Check: func() bool {
                                                                                                                                                                          		return true
                                                                                                                                                                          	}}, -1, Verbose(true), VerboseWriter(os.Stdout))
                                                                                                                                                                          if err != nil {
                                                                                                                                                                          	fmt.Printf("SpawnGeneric failed: %v\n", err)
                                                                                                                                                                          	return
                                                                                                                                                                          }
                                                                                                                                                                          re := regexp.MustCompile("testrouter#")
                                                                                                                                                                          var interactCmdSorted []string
                                                                                                                                                                          for k := range cliMap {
                                                                                                                                                                          	interactCmdSorted = append(interactCmdSorted, k)
                                                                                                                                                                          }
                                                                                                                                                                          sort.Strings(interactCmdSorted)
                                                                                                                                                                          interact := func() {
                                                                                                                                                                          	for _, cmd := range interactCmdSorted {
                                                                                                                                                                          		if err := exp.Send(cmd + "\n"); err != nil {
                                                                                                                                                                          			fmt.Printf("exp.Send(%q) failed: %v\n", cmd+"\n", err)
                                                                                                                                                                          			return
                                                                                                                                                                          		}
                                                                                                                                                                          		out, _, err := exp.Expect(re, -1)
                                                                                                                                                                          		if err != nil {
                                                                                                                                                                          			fmt.Printf("exp.Expect(%v) failed: %v out: %v", re, err, out)
                                                                                                                                                                          			return
                                                                                                                                                                          		}
                                                                                                                                                                          	}
                                                                                                                                                                          }
                                                                                                                                                                          interact()
                                                                                                                                                                          
                                                                                                                                                                          waitCh <- nil
                                                                                                                                                                          exp.Close()
                                                                                                                                                                          wOut.Close()
                                                                                                                                                                          
                                                                                                                                                                          <-r
                                                                                                                                                                          
                                                                                                                                                                          �[34mSent:�[39m "show system uptime\n"
                                                                                                                                                                          �[32mMatch for RE:�[39m "testrouter#" found: ["testrouter#"] Buffer: Current time:      1998-10-13 19:45:47 UTC
                                                                                                                                                                          Time Source:       NTP CLOCK
                                                                                                                                                                          System booted:     1998-10-12 20:51:41 UTC (22:54:06 ago)
                                                                                                                                                                          Protocols started: 1998-10-13 19:33:45 UTC (00:12:02 ago)
                                                                                                                                                                          Last configured:   1998-10-13 19:33:45 UTC (00:12:02 ago) by abc
                                                                                                                                                                          12:45PM  up 22:54, 2 users, load averages: 0.07, 0.02, 0.01
                                                                                                                                                                          
                                                                                                                                                                          testuser@testrouter#
                                                                                                                                                                          �[34mSent:�[39m "show system users\n"
                                                                                                                                                                          �[32mMatch for RE:�[39m "testrouter#" found: ["testrouter#"] Buffer: 7:30PM  up 4 days,  2:26, 2 users, load averages: 0.07, 0.02, 0.01
                                                                                                                                                                          USER     TTY FROM              LOGIN@  IDLE WHAT
                                                                                                                                                                          root     d0  -                Fri05PM 4days -csh (csh)
                                                                                                                                                                          blue   p0 level5.company.net 7:30PM     - cli
                                                                                                                                                                          
                                                                                                                                                                          testuser@testrouter#
                                                                                                                                                                          �[34mSent:�[39m "show version\n"
                                                                                                                                                                          �[32mMatch for RE:�[39m "testrouter#" found: ["testrouter#"] Buffer: Cisco IOS Software, 3600 Software (C3660-I-M), Version 12.3(4)T
                                                                                                                                                                          
                                                                                                                                                                          TAC Support: http://www.cisco.com/tac
                                                                                                                                                                          Copyright (c) 1986-2003 by Cisco Systems, Inc.
                                                                                                                                                                          Compiled Thu 18-Sep-03 15:37 by ccai
                                                                                                                                                                          
                                                                                                                                                                          ROM: System Bootstrap, Version 12.0(6r)T, RELEASE SOFTWARE (fc1)
                                                                                                                                                                          ROM:
                                                                                                                                                                          
                                                                                                                                                                          C3660-1 uptime is 1 week, 3 days, 6 hours, 41 minutes
                                                                                                                                                                          System returned to ROM by power-on
                                                                                                                                                                          System image file is "slot0:tftpboot/c3660-i-mz.123-4.T"
                                                                                                                                                                          
                                                                                                                                                                          Cisco 3660 (R527x) processor (revision 1.0) with 57344K/8192K bytes of memory.
                                                                                                                                                                          Processor board ID JAB055180FF
                                                                                                                                                                          R527x CPU at 225Mhz, Implementation 40, Rev 10.0, 2048KB L2 Cache
                                                                                                                                                                          
                                                                                                                                                                          3660 Chassis type: ENTERPRISE
                                                                                                                                                                          2 FastEthernet interfaces
                                                                                                                                                                          4 Serial interfaces
                                                                                                                                                                          DRAM configuration is 64 bits wide with parity disabled.
                                                                                                                                                                          125K bytes of NVRAM.
                                                                                                                                                                          16384K bytes of processor board System flash (Read/Write)
                                                                                                                                                                          
                                                                                                                                                                          Flash card inserted. Reading filesystem...done.
                                                                                                                                                                          20480K bytes of processor board PCMCIA Slot0 flash (Read/Write)
                                                                                                                                                                          
                                                                                                                                                                          Configuration register is 0x2102
                                                                                                                                                                          
                                                                                                                                                                          testrouter#
                                                                                                                                                                          

                                                                                                                                                                          func VerboseWriter

                                                                                                                                                                          func VerboseWriter(w io.Writer) Option

                                                                                                                                                                            VerboseWriter sets an alternate destination for verbose logs.

                                                                                                                                                                            type Status

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

                                                                                                                                                                              Status contains an errormessage and a status code.

                                                                                                                                                                              func NewStatus

                                                                                                                                                                              func NewStatus(code codes.Code, msg string) *Status

                                                                                                                                                                                NewStatus creates a Status with the provided code and message.

                                                                                                                                                                                func NewStatusf

                                                                                                                                                                                func NewStatusf(code codes.Code, format string, a ...interface{}) *Status

                                                                                                                                                                                  NewStatusf returns a Status with the provided code and a formatted message.

                                                                                                                                                                                  func (*Status) Err

                                                                                                                                                                                  func (s *Status) Err() error

                                                                                                                                                                                    Err is a helper to handle errors.

                                                                                                                                                                                    func (*Status) Error

                                                                                                                                                                                    func (s *Status) Error() string

                                                                                                                                                                                      Error is here to adhere to the error interface.

                                                                                                                                                                                      type Tag

                                                                                                                                                                                      type Tag int32

                                                                                                                                                                                        Tag represents the state for a Caser.

                                                                                                                                                                                        type TimeoutError

                                                                                                                                                                                        type TimeoutError int

                                                                                                                                                                                          TimeoutError is the error returned by all Expect functions upon timer expiry.

                                                                                                                                                                                          func (TimeoutError) Error

                                                                                                                                                                                          func (t TimeoutError) Error() string

                                                                                                                                                                                            Error implements the Error interface.

                                                                                                                                                                                            Source Files

                                                                                                                                                                                            Directories

                                                                                                                                                                                            Path Synopsis
                                                                                                                                                                                            examples
                                                                                                                                                                                            newspawner
                                                                                                                                                                                            telnet creates a new Expect spawner for Telnet.
                                                                                                                                                                                            telnet creates a new Expect spawner for Telnet.
                                                                                                                                                                                            process
                                                                                                                                                                                            process is a simple example of spawning a process from the expect package.
                                                                                                                                                                                            process is a simple example of spawning a process from the expect package.