Contents

EEM CLI Library Command Extensions

All command-line interface (CLI) library command extensions belong to the ::cisco::eem namespace.

This library provides users the ability to run CLI commands and get the output of the commands in Tcl. Users can use commands in this library to spawn an exec and open a virtual terminal channel to it, write the command to execute to the channel so that the command will be executed by exec, and read back the output of the command.

There are two types of CLI commands: interactive commands and non-interactive commands.

For interactive commands, after the command is entered, there will be a "Q&A" phase in which the device will ask for different user options, and the user is supposed to enter the answer for each question. Only after all the questions have been answered properly will the command run according to the user’s options until completion.

For noninteractive commands, once the command is entered, the command will run to completion. To run different types of commands using an EEM script, different CLI library command sequences should be used, which are documented in the "Using the CLI Library to Run a Noninteractive Command" section and in the "Using the CLI Library to Run an Interactive Command" section in the cli_write Tcl command.

The vty lines are allocated from the pool of vty lines that are configured using the line vty CLI configuration command. EEM will use a vty line when a vty line is not being used by EEM and there are available vty lines. EEM will also use a vty line when EEM is already using a vty line and there are three or more vty lines available. Be aware that the connection will fail when fewer than three vty lines are available, preserving the remaining vty lines for Telnet use.

Your release may support XML-PI. For details about the XML-PI support, the new CLI library command extensions, and some examples of how to implement XML-PI, see EEM CLI Library XML-PI Support.

cli_close

Closes the exec process and releases the vty and the specified channel handler connected to the command-line interface (CLI).

Syntax

cli_close fd tty_id

Arguments

fd

(Mandatory) The CLI channel handler.

tty_id

(Mandatory) The TTY ID returned from the cli_open command extension.

Result String

None

Set _cerrno

Cannot close the channel.

cli_exec

Writes the command to the specified channel handler to execute the command. Then reads the output of the command from the channel and returns the output.

Syntax

cli_exec fd cmd

Arguments

fd

(Mandatory) The command-line interface (CLI) channel handler.

cmd

(Mandatory) The CLI command to execute.

Result String

The output of the CLI command executed.

Set _cerrno

Error reading the channel.

cli_get_ttyname

Returns the real and pseudo TTY names for a given TTY ID.

Syntax

cli_get_ttyname tty_id

Arguments

tty_id

(Mandatory) The TTY ID returned from the cli_open command extension.

Result String

pty %s tty %s

Set _cerrno

None

cli_open

Allocates a vty, creates an EXEC command-line interface (CLI) session, and connects the vty to a channel handler. Returns an array including the channel handler.


Note


Each call to cli_open initiates a Cisco IOS EXEC session that allocates a Cisco IOS vty line. The vty remains in use until the cli_close routine is called. The vty lines are allocated from the pool of vty lines that are configured using the line vty CLI configuration command. EEM will use a vty line when a vty line is not being used by EEM and there are available vty lines. EEM will also use a vty line when EEM is already using a vty line and there are three or more vty lines available. Be aware that the connection will fail when fewer than three vty lines are available, preserving the remaining vty lines for Telnet use


Syntax

cli_open

Arguments

None

Result String

"tty_id {%s} pty {%d} tty {%d} fd {%d}"

Event Type

Description

tty_id

TTY ID.

pty

PTY device name.

tty

TTY device name.

fd

CLI channel handler.

Set _cerrno

  • Cannot get pty for EXEC.
  • Cannot create an EXEC CLI session.
  • Error reading the first prompt.

cli_read

Reads the command output from the specified command-line interface (CLI) channel handler until the pattern of the device prompt occurs in the contents read. Returns all the contents read up to the match.

Syntax

cli_read fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

All the contents read.

Set _cerrno

Cannot get device name.


Note


This Tcl command extension will block waiting for the device prompt to show up in the contents read.


cli_read_drain

Reads and drains the command output of the specified command-line interface (CLI) channel handler. Returns all the contents read.

Syntax

cli_read_drain fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

All the contents read.

Set _cerrno

None

cli_read_line

Reads one line of the command output from the specified command-line interface (CLI) channel handler. Returns the line read.

Syntax

cli_read_line fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

The line read.

Set _cerrno

None


Note


This Tcl command extension will block waiting for the end of line to show up in the contents read.


cli_read_pattern

Reads the command output from the specified command-line interface (CLI) channel handler until the pattern that is to be matched occurs in the contents read. Returns all the contents read up to the match.


Note


The pattern matching logic attempts a match by looking at the command output data as it is delivered from the Cisco IOS command. The match is always done on the most recent 256 characters in the output buffer unless there are fewer characters available, in which case the match is done on fewer characters. If more than 256 characters in the output buffer are required for the match to succeed, the pattern will not match.


Syntax

cli_read_pattern fd ptn

Arguments

fd

(Mandatory) The CLI channel handler.

ptn

(Mandatory) The pattern to be matched when reading the command output from the channel.

Result String

All the contents read.

Set _cerrno

None


Note


This Tcl command extension will block waiting for the specified pattern to show up in the contents read.


cli_run

Iterates over the items in the clist and assumes that each one is a command-line-interface (CLI) command to be executed in the enable mode. On success, returns the output of all executed commands and on failure, returns error from the failure.

Syntax

cli_run clist

Arguments

clist

(Mandatory) The list of commands to be executed.

Result String

Output of all the commands that are executed or an error message.

Set _cerrno

None.

Sample Usage

The following example shows how to use the cli_run command extension.

set clist [list {sh run} {sh ver} {sh event man pol reg}]
cli_run { clist }

cli_run_interactive

Provides a sublist to the clist which has four items. On success, returns the output of all executed commands and on failure, returns error from the failure. Also uses arrays when possible as a way of making things easier to read later by keeping expect and reply separated.

Syntax

cli_run_interactive clist

Arguments

clist

(Mandatory) Sublist which has four items and each item has four subitems:

  • command
    • expect
    • an expected question
    • reply
    • reply to this question
  • a command to run
    • expect
    • an expected question
    • reply
    • reply to this question
  • responses
    • expect
    • an expected question
    • reply
    • reply to this question
  • a list of what to expect and what to reply.
    • expect
    • an expected question
    • reply
    • reply to this question

Result String

Output of all the commands that are executed or an error message.

Set _cerrno

None.

Sample Usage

The following example shows how to use the cli_ru_ interactive command extension.

set cmd1 "first command"
set cmd1_exp1 {[confirm]}
set cmd1_rep1 {y}
set cmd1_response [list [list expect $cmd1_exp1 reply $cmd1_rep1]]
set cmd2 "second command"
set cmd2_exp1 {save config}
set cmd2_rep1 {no}
set cmd2_exp2 {[confirm]}
set cmd2_rep2 {y}
set cmd2_response [list [list expect $cmd2_exp1 reply $cmd2_rep1] [list expect $cmd2_exp2 reply $cmd2_rep2]]
set cmd3 "third command"
set cmd3_exp1 {are you sure}
set cmd3_rep1 {yes}
set cmd3_exp2 {destination file}
set cmd3_rep2 {test.txt}
set cmd2_response [list [list expect $cmd3_exp1 reply $cmd3_rep1] [list expect $cmd3_exp2 reply $cmd3_rep2]]
set clist [list " command $cmd1 responses $cmd1_response" " command $cmd2 responses $cmd2_response" " command $cmd3 responses $cmd3_response"]
cli_run_interactive { clist }

cli_write

Writes the command that is to be executed to the specified CLI channel handler. The CLI channel handler executes the command.

Syntax

cli_write fd cmd

Arguments

fd

(Mandatory) The CLI channel handler.

cmd

(Mandatory) The CLI command to execute.

Result String

None

Set _cerrno

None

Sample Usage

As an example, use configuration CLI commands to bring up Ethernet interface 1/0:

if [catch {cli_open} result] {
puts stderr $result
exit 1
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "config t"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "interface Ethernet1/0"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "no shut"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "end"} result] {
puts stderr $result
exit 1
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} } result] {
puts stderr $result
exit 1

Using the CLI Library to Run a Noninteractive Command

To run a noninteractive command, use the cli_exec command extension to issue the command, and then wait for the complete output and the device prompt. For example, the following shows the use of configuration CLI commands to bring up Ethernet interface 1/0:

if [catch {cli_open} result] {
error $result $errorInfo
} else {
set fd $result
}
if [catch {cli_exec $fd "en"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "config t"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "interface Ethernet1/0"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "no shut"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "end"} result] {
error $result $errorInfo
}
if [catch {cli_close $fd} result] {
error $result $errorInfo
}

Using the CLI Library to Run an Interactive Command

To run interactive commands, three phases are needed:

  • Phase 1: Issue the command using the cli_write command extension.
  • Phase 2: Q&A Phase. Use the cli_read_pattern command extension to read the question (the regular pattern that is specified to match the question text) and the cli_write command extension to write back the answers alternately.
  • Phase 3: Noninteractive phase. All questions have been answered, and the command will run to completion. Use the cli_read command extension to wait for the complete output of the command and the device prompt.

For example, use CLI commands to do squeeze bootflash: and save the output of this command in the Tcl variable cmd_output.

if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
error $result $errorInfo
}
 
# Phase 1: issue the command
if [catch {cli_write $cli1(fd) "squeeze bootflash:"} result] {
error $result $errorInfo
}
 
# Phase 2: Q&A phase
# wait for prompted question:
# All deleted files will be removed. Continue? [confirm]
if [catch {cli_read_pattern $cli1(fd) "All deleted"} result] {
error $result $errorInfo
}
# write a newline character
if [catch {cli_write $cli1(fd) "\n"} result] {
error $result $errorInfo
}
# wait for prompted question:
# Squeeze operation may take a while. Continue? [confirm]
if [catch {cli_read_pattern $cli1(fd) "Squeeze operation"} result] {
error $result $errorInfo
}
# write a newline character
if [catch {cli_write $cli1(fd) "\n"} result] {
error $result $errorInfo
}
 
# Phase 3: noninteractive phase
# wait for command to complete and the router prompt
if [catch {cli_read $cli1(fd) } result] {
error $result $errorInfo
} else {
set cmd_output $result
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
error $result $errorInfo
}

The following example causes a device to be reloaded using the CLI reload command. Note that the EEM action_reload command accomplishes the same result in a more efficient manner, but this example is presented to illustrate the flexibility of the CLI library for interactive command execution.

# 1. execute the reload command
if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
    error $result $errorInfo
}
if [catch {cli_write $cli1(fd) "reload"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_read_pattern $cli1(fd) ".*(System configuration has been modified. Save\\\? \\\[yes/no\\\]: )"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_write $cli1(fd) "no"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_read_pattern $cli1(fd) ".*(Proceed with reload\\\? \\\[confirm\\\])"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_write $cli1(fd) "y"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
    error $result $errorInfo
}


EEM CLI Library Command Extensions

EEM CLI Library Command Extensions

All command-line interface (CLI) library command extensions belong to the ::cisco::eem namespace.

This library provides users the ability to run CLI commands and get the output of the commands in Tcl. Users can use commands in this library to spawn an exec and open a virtual terminal channel to it, write the command to execute to the channel so that the command will be executed by exec, and read back the output of the command.

There are two types of CLI commands: interactive commands and non-interactive commands.

For interactive commands, after the command is entered, there will be a "Q&A" phase in which the device will ask for different user options, and the user is supposed to enter the answer for each question. Only after all the questions have been answered properly will the command run according to the user’s options until completion.

For noninteractive commands, once the command is entered, the command will run to completion. To run different types of commands using an EEM script, different CLI library command sequences should be used, which are documented in the "Using the CLI Library to Run a Noninteractive Command" section and in the "Using the CLI Library to Run an Interactive Command" section in the cli_write Tcl command.

The vty lines are allocated from the pool of vty lines that are configured using the line vty CLI configuration command. EEM will use a vty line when a vty line is not being used by EEM and there are available vty lines. EEM will also use a vty line when EEM is already using a vty line and there are three or more vty lines available. Be aware that the connection will fail when fewer than three vty lines are available, preserving the remaining vty lines for Telnet use.

Your release may support XML-PI. For details about the XML-PI support, the new CLI library command extensions, and some examples of how to implement XML-PI, see EEM CLI Library XML-PI Support.

cli_close

Closes the exec process and releases the vty and the specified channel handler connected to the command-line interface (CLI).

Syntax

cli_close fd tty_id

Arguments

fd

(Mandatory) The CLI channel handler.

tty_id

(Mandatory) The TTY ID returned from the cli_open command extension.

Result String

None

Set _cerrno

Cannot close the channel.

cli_exec

Writes the command to the specified channel handler to execute the command. Then reads the output of the command from the channel and returns the output.

Syntax

cli_exec fd cmd

Arguments

fd

(Mandatory) The command-line interface (CLI) channel handler.

cmd

(Mandatory) The CLI command to execute.

Result String

The output of the CLI command executed.

Set _cerrno

Error reading the channel.

cli_get_ttyname

Returns the real and pseudo TTY names for a given TTY ID.

Syntax

cli_get_ttyname tty_id

Arguments

tty_id

(Mandatory) The TTY ID returned from the cli_open command extension.

Result String

pty %s tty %s

Set _cerrno

None

cli_open

Allocates a vty, creates an EXEC command-line interface (CLI) session, and connects the vty to a channel handler. Returns an array including the channel handler.


Note


Each call to cli_open initiates a Cisco IOS EXEC session that allocates a Cisco IOS vty line. The vty remains in use until the cli_close routine is called. The vty lines are allocated from the pool of vty lines that are configured using the line vty CLI configuration command. EEM will use a vty line when a vty line is not being used by EEM and there are available vty lines. EEM will also use a vty line when EEM is already using a vty line and there are three or more vty lines available. Be aware that the connection will fail when fewer than three vty lines are available, preserving the remaining vty lines for Telnet use


Syntax

cli_open

Arguments

None

Result String

"tty_id {%s} pty {%d} tty {%d} fd {%d}"

Event Type

Description

tty_id

TTY ID.

pty

PTY device name.

tty

TTY device name.

fd

CLI channel handler.

Set _cerrno

  • Cannot get pty for EXEC.
  • Cannot create an EXEC CLI session.
  • Error reading the first prompt.

cli_read

Reads the command output from the specified command-line interface (CLI) channel handler until the pattern of the device prompt occurs in the contents read. Returns all the contents read up to the match.

Syntax

cli_read fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

All the contents read.

Set _cerrno

Cannot get device name.


Note


This Tcl command extension will block waiting for the device prompt to show up in the contents read.


cli_read_drain

Reads and drains the command output of the specified command-line interface (CLI) channel handler. Returns all the contents read.

Syntax

cli_read_drain fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

All the contents read.

Set _cerrno

None

cli_read_line

Reads one line of the command output from the specified command-line interface (CLI) channel handler. Returns the line read.

Syntax

cli_read_line fd

Arguments

fd

(Mandatory) The CLI channel handler.

Result String

The line read.

Set _cerrno

None


Note


This Tcl command extension will block waiting for the end of line to show up in the contents read.


cli_read_pattern

Reads the command output from the specified command-line interface (CLI) channel handler until the pattern that is to be matched occurs in the contents read. Returns all the contents read up to the match.


Note


The pattern matching logic attempts a match by looking at the command output data as it is delivered from the Cisco IOS command. The match is always done on the most recent 256 characters in the output buffer unless there are fewer characters available, in which case the match is done on fewer characters. If more than 256 characters in the output buffer are required for the match to succeed, the pattern will not match.


Syntax

cli_read_pattern fd ptn

Arguments

fd

(Mandatory) The CLI channel handler.

ptn

(Mandatory) The pattern to be matched when reading the command output from the channel.

Result String

All the contents read.

Set _cerrno

None


Note


This Tcl command extension will block waiting for the specified pattern to show up in the contents read.


cli_run

Iterates over the items in the clist and assumes that each one is a command-line-interface (CLI) command to be executed in the enable mode. On success, returns the output of all executed commands and on failure, returns error from the failure.

Syntax

cli_run clist

Arguments

clist

(Mandatory) The list of commands to be executed.

Result String

Output of all the commands that are executed or an error message.

Set _cerrno

None.

Sample Usage

The following example shows how to use the cli_run command extension.

set clist [list {sh run} {sh ver} {sh event man pol reg}]
cli_run { clist }

cli_run_interactive

Provides a sublist to the clist which has four items. On success, returns the output of all executed commands and on failure, returns error from the failure. Also uses arrays when possible as a way of making things easier to read later by keeping expect and reply separated.

Syntax

cli_run_interactive clist

Arguments

clist

(Mandatory) Sublist which has four items and each item has four subitems:

  • command
    • expect
    • an expected question
    • reply
    • reply to this question
  • a command to run
    • expect
    • an expected question
    • reply
    • reply to this question
  • responses
    • expect
    • an expected question
    • reply
    • reply to this question
  • a list of what to expect and what to reply.
    • expect
    • an expected question
    • reply
    • reply to this question

Result String

Output of all the commands that are executed or an error message.

Set _cerrno

None.

Sample Usage

The following example shows how to use the cli_ru_ interactive command extension.

set cmd1 "first command"
set cmd1_exp1 {[confirm]}
set cmd1_rep1 {y}
set cmd1_response [list [list expect $cmd1_exp1 reply $cmd1_rep1]]
set cmd2 "second command"
set cmd2_exp1 {save config}
set cmd2_rep1 {no}
set cmd2_exp2 {[confirm]}
set cmd2_rep2 {y}
set cmd2_response [list [list expect $cmd2_exp1 reply $cmd2_rep1] [list expect $cmd2_exp2 reply $cmd2_rep2]]
set cmd3 "third command"
set cmd3_exp1 {are you sure}
set cmd3_rep1 {yes}
set cmd3_exp2 {destination file}
set cmd3_rep2 {test.txt}
set cmd2_response [list [list expect $cmd3_exp1 reply $cmd3_rep1] [list expect $cmd3_exp2 reply $cmd3_rep2]]
set clist [list " command $cmd1 responses $cmd1_response" " command $cmd2 responses $cmd2_response" " command $cmd3 responses $cmd3_response"]
cli_run_interactive { clist }

cli_write

Writes the command that is to be executed to the specified CLI channel handler. The CLI channel handler executes the command.

Syntax

cli_write fd cmd

Arguments

fd

(Mandatory) The CLI channel handler.

cmd

(Mandatory) The CLI command to execute.

Result String

None

Set _cerrno

None

Sample Usage

As an example, use configuration CLI commands to bring up Ethernet interface 1/0:

if [catch {cli_open} result] {
puts stderr $result
exit 1
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "config t"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "interface Ethernet1/0"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "no shut"} result] {
puts stderr $result
exit 1
}
if [catch {cli_exec $cli1(fd) "end"} result] {
puts stderr $result
exit 1
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} } result] {
puts stderr $result
exit 1

Using the CLI Library to Run a Noninteractive Command

To run a noninteractive command, use the cli_exec command extension to issue the command, and then wait for the complete output and the device prompt. For example, the following shows the use of configuration CLI commands to bring up Ethernet interface 1/0:

if [catch {cli_open} result] {
error $result $errorInfo
} else {
set fd $result
}
if [catch {cli_exec $fd "en"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "config t"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "interface Ethernet1/0"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "no shut"} result] {
error $result $errorInfo
}
if [catch {cli_exec $fd "end"} result] {
error $result $errorInfo
}
if [catch {cli_close $fd} result] {
error $result $errorInfo
}

Using the CLI Library to Run an Interactive Command

To run interactive commands, three phases are needed:

  • Phase 1: Issue the command using the cli_write command extension.
  • Phase 2: Q&A Phase. Use the cli_read_pattern command extension to read the question (the regular pattern that is specified to match the question text) and the cli_write command extension to write back the answers alternately.
  • Phase 3: Noninteractive phase. All questions have been answered, and the command will run to completion. Use the cli_read command extension to wait for the complete output of the command and the device prompt.

For example, use CLI commands to do squeeze bootflash: and save the output of this command in the Tcl variable cmd_output.

if [catch {cli_open} result] {
error $result $errorInfo
} else {
array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
error $result $errorInfo
}
 
# Phase 1: issue the command
if [catch {cli_write $cli1(fd) "squeeze bootflash:"} result] {
error $result $errorInfo
}
 
# Phase 2: Q&A phase
# wait for prompted question:
# All deleted files will be removed. Continue? [confirm]
if [catch {cli_read_pattern $cli1(fd) "All deleted"} result] {
error $result $errorInfo
}
# write a newline character
if [catch {cli_write $cli1(fd) "\n"} result] {
error $result $errorInfo
}
# wait for prompted question:
# Squeeze operation may take a while. Continue? [confirm]
if [catch {cli_read_pattern $cli1(fd) "Squeeze operation"} result] {
error $result $errorInfo
}
# write a newline character
if [catch {cli_write $cli1(fd) "\n"} result] {
error $result $errorInfo
}
 
# Phase 3: noninteractive phase
# wait for command to complete and the router prompt
if [catch {cli_read $cli1(fd) } result] {
error $result $errorInfo
} else {
set cmd_output $result
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
error $result $errorInfo
}

The following example causes a device to be reloaded using the CLI reload command. Note that the EEM action_reload command accomplishes the same result in a more efficient manner, but this example is presented to illustrate the flexibility of the CLI library for interactive command execution.

# 1. execute the reload command
if [catch {cli_open} result] {
    error $result $errorInfo
} else {
    array set cli1 $result
}
if [catch {cli_exec $cli1(fd) "en"} result] {
    error $result $errorInfo
}
if [catch {cli_write $cli1(fd) "reload"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_read_pattern $cli1(fd) ".*(System configuration has been modified. Save\\\? \\\[yes/no\\\]: )"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_write $cli1(fd) "no"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_read_pattern $cli1(fd) ".*(Proceed with reload\\\? \\\[confirm\\\])"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_write $cli1(fd) "y"} result] {
    error $result $errorInfo
} else {
    set cmd_output $result
}
if [catch {cli_close $cli1(fd) $cli1(tty_id)} result] {
    error $result $errorInfo
}