The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Mnet::Expect::Cli - Expect sessions to command line interfaces

SYNOPSIS

    # refer also to Mnet::Expect
    use Mnet::Expect::Cli;

    # prepare ssh command with host/key checking disabled
    my @ssh = qw(
        ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
    );

    # connect via ssh for user to specified host, prompt for password
    my $expect = Mnet::Expect::Cli->new({
        spawn       => [ @ssh, "user\@1.2.3.4" ],
        password_in => 1,
    });

    # gather output for specified command over ssh
    my $output = $expect->command("ls");

    # close ssh session
    $expect->close;

DESCRIPTION

Mnet::Expect::Cli can be used to spawn Expect processes, which can be used to programmatically control command line sessions to devices, with support for Mnet options, logging, caching, and testing.

Refer to the Mnet::Expect module, whose methods are inherited by objects created with this module. Also refer to Mnet::Expect::Cli::Ios, which builds on this module,

METHODS

Mnet::Expect::Cli implements the methods listed below.

new

    $expect = Mnet::Expect::Cli->new(\%opts)

This method can be used to create new Mnet::Expect::Cli objects.

The following input opts may be specified, in addition to options documented in the Mnet::Expect module new method:

    delay           millseconds delay for command prompt detection
    eol_unix        default true for output with unix /n eol chars only
    failed_re       set to speed login failures, disabled by default
    log_login       default undef uses Mnet::Expect log_expect logging
    paging_key      default space key to send for pagination prompt
    paging_re       default handles common prompts, refer to paging_re
    password        set to password for spawned command, if needed
    password_in     stderr prompt for stdin entry of password if not set
    password_re     undef to skip password/code/phrase prompt detection
    prompt_re       undef to disable post-login prompt detect, see below
    timeout         seconds for Expect restart_timeout_upon_receive
    username        set to username for spawned command, if needed
    username_re     undef to skip login/user/username promt detection

An error is issued if there are login problems.

For example, the following call will start an ssh expect session to a device with host key checking disabled:

    # refer to SYNOPSIS example for ssh with host/key checks disabled
    my $expect = Mnet::Expect::Cli->new({
        spawn => "ssh user@1.2.3.4", password_in => 1
    });

Set failed_re to detect failed logins faster, as long as there's no conflict with text that appears in login banners. For example:

    (?i)(closed|error|denied|fail|incorrect|invalid|refused|sorry)

A default prompt_re regex string is used by this method to detect and confirm the specific prompt text in use on a connected system, after login. When this happens prompt_re is rewritten with the detected prompt text, which is used by the command method to detect the end of command output.

By default prompts ending with $ % # : > are detected, this can be changed by setting prompt_re to a different regex string when calling the new method, or disabled by setting to undef, note that prompt_re needs to match the entire prompt line, not just the ending:

    (^|\r|\n)\S.*(\$|\%|#|:|>) ?(\r|\n|$)

Refer also to the prompt_re method which can be used to examine or change prompt_re for an existing session returned by this method.

Refer to the Mnet::Expect module for more information.

close

    $expect->close($command)

This method sends closes the current expect session, sending the optional input command first. Timeouts and disconnects are gracefully handled. Refer to the close method in the Mnet::Expect module for more information.

command

    $output = $expect->command($command, $timeout, \@prompts)

This method returns output from the specified command sent to the current expect cli session, or undefined if there was a timeout.

Note that this method caches command output, so that if the exact same command is sent repeatedly the first output from the connected device will be returned for subsequent calls. Refer to the command_cache_clear method for more info.

The optional timeout argument can be used to override the default timeout for the new object.

The optional prompts reference argument can be used to handle prompts that may occur when running a command, such as confirmation prompts. It should contain pairs of regex strings and responses. The regex string values should be what goes in between the forward slash characters of a regular expression. The response can be a string that is sent to the expect session with or without a carraige return, or may be a code reference that gets the current object and output as input args and returns a response string. A null prompt regex string is activated for timeouts and disconnects. An undef prompt response causes an immediate return of output.

    # sends $command, uses default timeout, defines some prompts
    my $output = $expect->command($command, undef, [

        # send 1.2.3.4 and carraige return if matched by expect -re /ip/
        'ip' => "1.2.3.4\r",

        # code ref
        'confirm? ' => sub { my $output = shift; return "y" },

        # returns received output on timeout, might be undef
        '' => undef,

    ]);

By default the end of command output is recognized using the prompt_re string detected by the new method after login. Refer to the new and prompt_re methods for more information.

command_cache_clear

    $expect->command_cache_clear

This method can be used to clear the cache used by the command method.

Normally the command method caches the outputs for all executed commands, returning cached output when the same command is executed subsequently. When the cache is cleared the command method will execute the next instance of any specific command instead of returning cached output.

delay

    $delay = $expect->delay($delay)

Get and/or set a new delay time in milliseconds for the current object. This delay is used when detecting extra command, prompt, or pagination output.

A good rule of thumb may be to set this delay to at least the round trip response time for a response from the connected process.

paging_re

    $paging_re = $expect->paging_re($paging_re)

Get and/or set new paging_re for the current object.

Following are known pagination prompts covered by the default paging_re:

    junos           =~ /^---\(more( \d\d?%)?\)---$/
    cisco ASA       =~ /<--- More --->/
    cisco ios       =~ /--more--/
    cisco ios 15    =~ /--More--/

Following are other observed pagination prompts, not covered by default:

    linux more cmd  =~ /--More--\(\d\d?%\)/

Note that matched pagination text is not appended to command output. Refer also to the command method in this module for more information.

prompt_re

    $prompt_re = $expect->prompt_re($prompt_re)

This method can be used to get and/or set the prompt_re regex string for an existing object, which is used by the command method to detect the end of output for a sent command. The prompt_re regex string should be specific enough to detect the cli prompt without matching any other command outputs.

By default the new method sets a device specific prompt_re for the rest of the session from the first prompt detected after login, confirmed by sending a carraige return and getting the same specifc prompt back again. This prompt detection can be adjusted or disabled, refer to the new method for more info.

Note that normally prompt_re should start with a regex caret symbol, and end with a regex dollar sign, so that all characters in the command prompt line are matched, and to avoid spurrious matches in command outputs. Be aware of any spaces that at the end of a prompt, as in the example below:

    $expect->prompt_re('^st-city-dev> $');

Also note that the /Q and /E escape sequences do not appear to be recognized by expect, and they should not be used in prompt_re.

timeout

    $timeout = $expect->timeout($timeout)

Get and/or set a new timeout for the current object, refer to the Expect module for more information.

TESTING

Mnet::Test --record and --replay command line options are supported by this module, and will record and replay command method outputs associated with calls to the command method, integrated with the command_cache_clear method.

Refer to the Mnet::Test module for more information.

SEE ALSO

Expect

Mnet

Mnet::Expect

Mnet::Expect::Cli::Ios

Mnet::Log

Mnet::Opts::Cli

Mnet::Test