-
Notifications
You must be signed in to change notification settings - Fork 5
TCLI Power Users Guide
TCLI can be run in either batch or interactive modes.
In batch mode, commands and settings are provided as flags and the output is printed on stdout.
Multiple commands are newline separated.
# Collect some diagnostic from device_a.
tcli -C 'show version
show chassis
sh ip ospf neighbor' -T device_a'
Scope of target devices to send commands to is controlled by expressions for what to include (targets) and to exclude (xtargets).
The target can be a literal device_a, or several literals comma separated (note that there are no spaces) like: device_a,device_b or instead of a literal, a regular expression is indicated by prefixing a ^ to the entry i.e. ^device_(a|b) which would match both device_a and device_b.
Output Display engines post process data. The display formats of csv, tbl and nvp are supported (covered below). Commands that cannot be handled by the display engine are returned in raw format (unformatted).
# Show version of all devices in single table.
tcli -C 'show version' -T ^device_. -D csv
Most of the power of TCLI is in the interactive mode. Easiest way to reach this mode is supply no arguments at the commandline or by requesting it explicitly with the -I flag. e.g.
tcli
This mode will also be reached if the flags passed to TCLI are somehow incomplete for batch mode i.e. specifying targets and no corresponding commands in this case the environment of interactive mode will be pre populated by whatever flags were specified.
Interactive mode has two types of commands:
-
Escape Commands:
Commands destined for TCLI itself, used to modify the operating environment of TCLI. Escape commands are proceeded by a '/'. -
Target Commands:
Commands destined for the target devices. The commands are forwarded to the target list and then the resultant output is collated and displayed. Target commands are not proceeded by a /.
There is also an escape command ( /command ) that takes all its arguments and forwards them as a target command. This may seem redundant but allows the sending of target commands when in safemode which is discussed later.
Changes to the environment made to TCLI are persistent across commands.
To inspect the current environment.
#! /env
Targets: , XTargets:
Display: raw, Filter: default
Record: None, Recordall: None
Log: None, Logall: logall
Color: True, Scheme: light
Timeout: 30, Verbose: False
Safemode: True
In interactive mode a prompt is supplied that indicates some key environment variable (targets, target count, safemode). The running environment can be tailored with escape commands.
#!<device_a[1]*> !#
The above prompt indicates that the target string is device_a which matches a single target [1].
In the case of #! <^device_.[96]> !# the target is a regular expression that matches devices prefixed with device_ (96 in this case). The matched list of devices can be seen by issuing /expandtargets.
Because many devices may be matched by a target expression, particular care should be taken not to issue accidental commands via TCLI (see safemode below).
TCLI starts up with safemode as the default operation environment. In this mode commands are not sent to the targets until either the safemode is turned off or the commands are sent as part of the escape command .i.e. prefixed with /command.
Note: Ctrl-C will interrupt a running command and return to the prompt. It does not however stop the commands from being sent to the devices. Once a commands request is submitted to the backend it will be processed. The Ctrl-C will merely stop TCLI waiting for the command responses to return.
#! /safemode off
Note: A star '*' at the end of the prompt indicates when safemode is active.
A limited set of tab completion is available in interactive mode. This works for escape commands, so by typing / followed by tabbing, the possible completions will be displayed.
It also works to a limited extent for router commands, this support is dependent on the existence of TextFSM templates for the commands.
Online help is available with:
#! /help
In interactive mode it is possible to append to the existing target and xtarget entries.
Example:
#! /targets ^device_(a|b)
To confirm that we have matched correctly:
#! /expandtargets
device_a,device_b
To then add device_c to the targets
#! /targets+ device_c
#! <^device_(a|b),device_c[3]*> !#
#! /expandtargets
device_a,device_b,device_c
To remove device_a from this list we could build a new target list or alternatively it is possible to extend the xtargets .
#! /xtargets+ device_a
#! <^device_(a|b),device_c[2]*> !#
#! /expandtargets
device_b,device_c
Resetting the targets back to null:
#! /targets ^
Note: Care should be taken to preserve the existing xtargets string as this typically includes devices you would not normally want to send commands to. A default xtargets can be created by editing the .tclirc file (discussed below).
Many commands also have a shorthand equivalent which a single capitalised character. These are listed at the end of the description for each command in the online help and include:
| Command | Shorthand |
|---|---|
| targets | T |
| xtargets | X |
| display | D |
| safemode | S |
| exec | ! |
| command | C |
| play | P |
| filter | F |
So the following two lines are equivalent:
#! /targets+ targetlist
#! /T+ targetlist
By default TCLI starts up with colour enabled and assumes that the terminal is dark - hence the colour scheme chosen is light to gain maximum contrast.
Colour can be toggled on/off with the command:
#! /color
If your terminal has a light background then alternatively change the colour scheme to be dark for better contrast:
#! /color_scheme dark
If the file .tclirc exists in the users home directory then it will be read into the buffer 'startup' and 'played' to TCLI as if it was a regular buffer 'play' command. The contents of this file are then accessible from 'startup' buffer thereafter.
This allows users to customise the 'at start' environment of TCLI.
Example: if you prefer the 'dark' colour scheme and are comfortable without safemode enabled then add the following to your .tclirc :
#! /color_scheme dark
#! /safemode off
The timeout value determines how long to wait for the device accessor to return a result from any of the pending devices. This may need changing in unusual situations where the command output is large. The value is specified in seconds.
#! /timeout 120
Command output can be formatted by several display filters.
Change the display format with /display (or -D).
In the cases other than raw a filter engine extracts the significant fields and returns only this data in one of several formats.
Unprocessed device output. Command return data is displayed 'as is'.
Comma separated values suitable for importing into spreadsheets.
Command output is processed by the engine specified by filter and the data returned is in a CSV table. If there are multiple targets then they are included in the same table and the first column will be the target device name.
If data fields in the returned data are different between devices then they will be split into separate tables.
If no template exists for a command, hence it cannot be formatted, then it is returned in raw mode.
Host, ColAa, ColAb
device_a, hello, world
device_b, HELLO, WORLD
Output is formatted into a user friendly tabular data. Includes padded columns and row separators that are not as machine friendly as the CSV format but is clearer for humans to read.
Host ColAa ColAb
========================
device_a hello world
device_b HELLO WORLD
Display name value pairs. One per row, suitable for row based parsing. If multiple targets then the target name is embedded in the name field. Producing a line based format suitable for grep or parsing with scripts.
# LABEL Value
device_a.ColAa hello
device_a.ColAb world
device_b.ColAa HELLO
device_b.ColAb WORLD
The filter engine is the CLI Table textual output parser. TCLI extends the functionality to support suppressing unwanted data for more concise display. Values in the TextFSM template can be suppressed in the default response by adding the label Verbose to the Value entries in the template.
The set of fields returned by the engine is controlled by toggling the verbose command in TCLI. This is off by default and only the most significant fields are returned (intended to help data fit in a display). If verbose is true then the full set of fields are returned.
Commands and command output can be logged to a buffer with:
#! /log buffername
To log both router commands and system output such as escape commands and errors.
#! /logall buffername
Alternatively to record the commands issued but skip logging the data returned then use the record and recordall commands.
To record router commands issued:
#! /record buffername
Or to record both TCLI escape commands and commands sent to the targets:
#! /recordall buffername
Note: It is not possible to specify the same buffer as a destination for multiple log/record commands.
#! /log abuffer
#! /logall abuffer
Buffer: 'abuffer', already open for writing.
To see which buffers are currently in use then use the env command.
To stop writing to a log or record then either issue a logstop or recordstop command.
#! /logstop buffername
The commands logstop and recordstop are interchangeable.
#! /log abuffer
#! /recordstop abuffer
#! /logstop abuffer
Buffer not in use for logging or recording.
Buffers and buffer content persists after we are no longer writing to it. A buffer can be reused for logging/recording. It will be deleted and overwritten with the new data unless we specify a '+' as a command suffix.
To append log data:
#! /log+ buffername
To see the list of buffers active or previously used to date:
#! /bufferlist
If a .tclirc exists (discussed below) then there will be an initial buffer startup present.
Buffers can be edited with vi , even while being edited.
#! /vi buffername
Buffers can be read and written from the local host.
#! /read buffername filename
Example:
To read the file postmortem into buffer abuffer.
#! /read abuffer ~/postmortem
122 lines read.
The command write takes a buffer and writes it to a file.
For both read and write the filename supports tilde ~ and shell variable substitution.
So ~/$USER/file.txt is a valid destination and for the user harro , it will write to /home/harro/harro/file.txt .
A buffer can be 'played' to TCLI as if it was user input. The buffer could contain both TCLI commands and router commands.
To play the contents of a buffer:
#! /play buffername
Particular care should be taken so that you understand the contents of the buffer and the current running environment before playing out its contents. Attempting to playback a buffer that is currently in use for logging or recording will result in an error message.
Escape commands persist in interactive mode. Inline escape commands are a convenient way to supply overrides on a per command basis. Inline escape commands do not modify the persistent environment.
Inline escape commands follow the targeted command with a '//' rather than the usual '/'. There can be any number of them (the leftmost have precedence).
e.g. The following command sequence attempts to send a command to a single target and then repeats this with safemode disabled.
#! <[0]*> !#
#! /targets device_a
#! <device_a[1]*> !#
#! show version | grep boot
Safe mode on, command ignored.
#! <device_a[1]*> !#
#! show version | grep boot //safemode off
#!# device_a:show version | grep boot #!#
JUNOS Base OS boot [#####]
#! <device_a[1]*> !#
#! show version | grep boot
Safe mode on, command ignored.
Not all commands are supported in inline mode, some of them simply don't make sense in this context.
The following commands can be used inline:
* color
* color_scheme
* display
* exit
* filter
* log
* logall
* logstop
* record
* recordall
* recordstop
* safemode
* targets
* timeout
* verbose
* xtargets
The behaviour is identical to its regular usage with one exception of exit . The Exit command ceases inline command parsing at that point. Inline command parsing occurs from right to left. This might be necessary if the data portion of a command contains '//' strings. Inline command parsing will also cease on the first inline command that fails to parse.
So a command:
#! file list "a file name containing a
seemingly valid //targets inlinecommand" //exit
Will successfully list the file with the (somewhat contrived) name "a file name containing a seemingly valid //targets inlinecommand". Rather than sending 'file list "a file name containing a seemingly valid' to the targets 'inlinecommand'.
Further:
#! show version //display raw //bogus
Will fail to parse '//bogus' and send this entire string to the targets with none of the inline commands removed.
Tab completion unfortunately doesn't work on inline commands so take care to format them correctly to avoid them being sent to the target as targeted command data.
Many devices have multiple command lines (or 'modes'). Such as the cli or shell on a Juniper or Netscaler device, and the shell, cli and cligated on a unix device acting as a router.
The default mode is 'cli'. In the case of a box with no 'cli' (such as a unix host) then cli is mapped to the primary cli equivalent such as shell. The target mode can be changed with mode. For devices that don't support the specified mode then it will fall back to 'cli'.
#! show version
#! /mode shell
#! ls
Commands can be passed to the local host for execution with exec or ! . the resultant unix output will be captured by any active logall buffering.
Many target devices support target side filtering/formatting of command data.
Example: 'show version | grep Boot' is meaningful to a Juniper router.
TCLI supports target side pipes and also supports client side pipes with the '||' syntax. Multiple client pipes ('||') are permitted but must be to the 'right' of any target pipes ('|') and before (to the left) of any inline commands.
Example: The following will count how many tacacs servers are configured on the targets.
#! sh run | grep "tacacs-server host" || wc -l //safemode off
To avoid problems with '||' appearing in command data, quote the string containing the '||'. The parser will also stop splitting output for client pipes on encountering the first '|', so if '||' needs to appear in the command data unquoted then add a superfluous '|' to the right hand side.
So the following commands are OK:
#! sh run | grep "a || string"
#! sh run | grep || | grep .
But this will be incomplete:
#! sh run | grep ||
Note: The display formats other than 'raw' use filter engines to parse and extract data fields from the semi-structured device output. Using target side filters such as grep may defeat these parsing efforts and return incomplete data.