AOS7/8 Quick CLI Introduction
Posted: 20 May 2016 13:29
OS10K/6900/6860E come with a powerful differentiator: a Bash-based CLI. This basically gives the administrator unparalleled flexibility in what can be achieved with the device's CLI.
I am going, in this post, to document some of the things that may seem baffling with this CLI.
Q: Hey, the terminal behaves weirdly; for instance, it scrolls when I enter long lines
Yes, this behaviour is determined by what terminal you are currently using or, more accurately, which terminal you claim to be using.
The TERM environment variable can be used to modify that claim. For instance, you can set your terminal to "vt100" by typing:
To disable the scrolling behaviour, you need to be using a terminal that has a mapping for the 'cursor up' key. For instance, "vt100"
If you are capturing our session's echo, however, you will notice that even if you input is now correctly wrapped when reaching the last column, some invisible codes (CR/LF) are added. This is due to using a terminal that has "auto-margin" capability enabled.
To disable this capability, suffix your terminal name with the "-am" string; e.g. "vt100-am"
If you are running some sort of automation, Linux may be unable to determine what terminal you are using. In that case it will assume that you are using a dumb terminal with 80 columns, etc. You can work around this by beginning your script with this statement:
Q: When I enter a command ending with a quote, the prompt becomes weird and Bash is broken
It is, in fact, a feature. Here are a few things you need to be aware of:
Quotes (') and double quotes (") are used to enclose literal strings. Single quotes actually provide the most literal guard whereas double quotes will expand "$" variables.
Due to this behaviour, entering text such as:
will display "Hello" on a first row of you terminal, followed by "My name is Harold" on the next row.
Because you entered literal mode using a single quote, when you hit <Return>, Bash simply added that key's code to its literal string.
Literal mode was exited when you entered a closing single quote, which is why the second <Return> submitted the command to Bash.
Backslash (\) is a continuation character. This means that the current line is continued on the next line. You can keep continuing your input using a backslash character at the end of every new line your enter. To complete you entry, simply do not continue the last line.
Therefore, entering:
will display on a single row: "Hello My name is Harold"
As you can see, the continuation character allowed you to enter a single command using multiple lines. It did not break down the output because the first <Return> is not part of the input string.
HEREDOC (<<) is a form of I/O redirection that lets you feed a whole block to executables. HEREDOC takes a parameter and that parameter will be used by Bash to find the end of this pseudo I/O stream.
For instance, entering as root:
will display on every logged in user's terminal:
You told Bash that you were beginning a block of text and it would know that you were done when it encounters the string EOB at the beginning of a line.
Q: Can I substitue values in my command-line?
Value expansion is an extremely powerful tool but can be confusing to non-shell proficient users.
* and ?
The asterisk character ('*') and the question mark have very specific meanings in Bash.
The asterisk character can be used to replace an arbitrary number of characters of your command with a file name. This file needs to be referenced in a way that lets Bash find it.
For instance:
will list all the files found in the current directory that begin with the letter 'a' and end with the letter 'c'
Similarly, the question mark will be replaced by a single character. Therefore,
will list all files, in the current directory, that are three characters long, begin with the letter 'a' and end with the letter 'c'
-> Three characters long because '?' can only be replaced by a single character.
-> We also use '?' in CLI, at the end of command, to ask CLI for help on what arguments the current command accepts.
-> In the question mark's case, a side effect of shouldering two responsibilities is that they may interfere in the case where a single-character file is present in the current directory: Bash will replace this standalone '?' with the one-characters file name.
$, $$, $@, $1, $A, ...
You can use the dollar sign prefix to name variables.
Assigning a value to a variable is done *without* the dollar sign prefix (which Bash would otherwise attempt to expand during the assignment)
Therefore:
is proper syntax.
You can use variables in your CLI commands. For instance:
If you wish to block variable expansion, because for instance you wish to enter a password that contains the dollar sign, you may do so, as explained above, using single quotes.
But first, functions!
I am going to touch on functions very quickly because I will use a function to demonstrate how various dollar sign variables can be used.
A function is a piece of code that you can reuse after creating it (it does not run during its creation). It can take parameters and return a diagnostic value.
Let's imagine that you spend most of your day creating new VLANs and all your VLANs share most of their parameters. It would be nice to have a command that can be re-used without specifying these parameters every time.
To create a function, type its name followed by a pair of parenthesis and an opening curly brace.
To complete the function definition, enter a closing curly brace:
The body of your function (not created yet) will go between both curly braces.
You will then be able to run this function by entering its name:
$1..$9
These variables represent parameters passed to a function ("positional parameters")
If you write a Bash function e.g. "myvlans" and wish to handle parameters in the function, you will need to use those guys.
For instance:
This will create vlan 5.
$#
Now, you may wish to make this function a little smarter; for instance it should be able to handle cases when the user forgets to pass a parameter.
This will display an error message because $#, which represents the number of arguments that were passed to the function, is less than ("-lt") one.
$@ or $*
You may also wish to handle all the parameters at once. This is what this little guy provides.
Let's imagine, for a minute, that VLAN's syntax let you create as many VLANs as you desires, in one statement. This would be the correct way to pass all our arguments to the command.
shift
VLAN does not accept multiple VLAN ids as described in the previous paragraph. How can we go through our parameters list then?
Now, your script will create each VLAN using the "vlan" command. Every parameter will end up being seen as "parameter 1" thanks to the "shift" command.
"shift" moves ('shift') all the positional parameters down by one, every time it is invoked.
Therefore, with three parameters as in our above example:
This is great but wouldn't it be smarter for us to check that a vlan was successfuly created before moving on to the next one?
We can check for that using the previous command's return code, stored in $?
If "vlan $1" returned a value other than "0" which traditionally denotes success in the Unix world, the script complains and returns immediately.
$_ (dollar sign, underscore)
This little guy represents the most recently used parameter.
For instance:
should result in no vlan 5.
Adding user interaction
Say you would like for your script to ask a few questions and use your answers.
Use the "read" command to read user input. Here's how:
In conclusion, the "read" command is the user-based equivalent to "variable_name=value"
Q: What keyboard shortcuts are available?




(*) Backward/Forward history search mode
Let’s say that your history contains these lines:
Typing <Ctrl-R>sh will display “show vlan 1”
Typing <Ctrl-R> will display “show vlan 5”
Typing <Ctrl-S> will display “show vlan 1”
Typing <Ctrl-J> will let you start editing the latter command.
(**) Repeating a command
Let’s say you wish to move the cursor to the end of the next third word:
Typing Alt-3 Alt-F will do the trick.
More shortcuts
There are more shortcuts that you could use but I did not mention them here because they are quite complex to master; they are mostly a programmer’s friend.
The “other” mode
As if this wasn’t enough information to memorize, this set of commands matches the so-called “Emacs” mode. An alternate, incompatible set of commands known as “vi” mode is also available.
Further reading
Here is a list of external resources that address various shell-related topics more in depth:
Quoting: difference between single quotes and double quotes
http://muffinresearch.co.uk/archives/20 ... d-strings/
Quoting: a synthetic view
http://bash.cyberciti.biz/guide/Quoting
Bash scripting for beginners
http://www.linuxconfig.org/Bash_scripting_Tutorial
Bash scripting for power users
http://tldp.org/LDP/abs/html/
Bash history management
http://www.catonmat.net/blog/the-defini ... e-history/
I am going, in this post, to document some of the things that may seem baffling with this CLI.
Q: Hey, the terminal behaves weirdly; for instance, it scrolls when I enter long lines
Yes, this behaviour is determined by what terminal you are currently using or, more accurately, which terminal you claim to be using.
The TERM environment variable can be used to modify that claim. For instance, you can set your terminal to "vt100" by typing:
Code: Select all
export TERM=vt100To disable the scrolling behaviour, you need to be using a terminal that has a mapping for the 'cursor up' key. For instance, "vt100"
If you are capturing our session's echo, however, you will notice that even if you input is now correctly wrapped when reaching the last column, some invisible codes (CR/LF) are added. This is due to using a terminal that has "auto-margin" capability enabled.
To disable this capability, suffix your terminal name with the "-am" string; e.g. "vt100-am"
If you are running some sort of automation, Linux may be unable to determine what terminal you are using. In that case it will assume that you are using a dumb terminal with 80 columns, etc. You can work around this by beginning your script with this statement:
Code: Select all
export TERM=vt100-amIt is, in fact, a feature. Here are a few things you need to be aware of:
Quotes (') and double quotes (") are used to enclose literal strings. Single quotes actually provide the most literal guard whereas double quotes will expand "$" variables.
Due to this behaviour, entering text such as:
Code: Select all
echo 'Hello,<Return>
My name is Harold'<Return>Because you entered literal mode using a single quote, when you hit <Return>, Bash simply added that key's code to its literal string.
Literal mode was exited when you entered a closing single quote, which is why the second <Return> submitted the command to Bash.
Backslash (\) is a continuation character. This means that the current line is continued on the next line. You can keep continuing your input using a backslash character at the end of every new line your enter. To complete you entry, simply do not continue the last line.
Therefore, entering:
Code: Select all
echo Hello,\<Return>
My name is Harold<Return>As you can see, the continuation character allowed you to enter a single command using multiple lines. It did not break down the output because the first <Return> is not part of the input string.
HEREDOC (<<) is a form of I/O redirection that lets you feed a whole block to executables. HEREDOC takes a parameter and that parameter will be used by Bash to find the end of this pseudo I/O stream.
For instance, entering as root:
Code: Select all
wall <<EOB<Return>
Hello,<Return>
My name is Harold<Return>
EOB<Return>Broadcast message from root (<Date>):
Hello,
My name is Harold
You told Bash that you were beginning a block of text and it would know that you were done when it encounters the string EOB at the beginning of a line.
Q: Can I substitue values in my command-line?
Value expansion is an extremely powerful tool but can be confusing to non-shell proficient users.
* and ?
The asterisk character ('*') and the question mark have very specific meanings in Bash.
The asterisk character can be used to replace an arbitrary number of characters of your command with a file name. This file needs to be referenced in a way that lets Bash find it.
For instance:
Code: Select all
ls a*cSimilarly, the question mark will be replaced by a single character. Therefore,
Code: Select all
ls a?c-> Three characters long because '?' can only be replaced by a single character.
-> We also use '?' in CLI, at the end of command, to ask CLI for help on what arguments the current command accepts.
-> In the question mark's case, a side effect of shouldering two responsibilities is that they may interfere in the case where a single-character file is present in the current directory: Bash will replace this standalone '?' with the one-characters file name.
$, $$, $@, $1, $A, ...
You can use the dollar sign prefix to name variables.
Assigning a value to a variable is done *without* the dollar sign prefix (which Bash would otherwise attempt to expand during the assignment)
Therefore:
Code: Select all
A="oh hello there"
echo $AYou can use variables in your CLI commands. For instance:
Code: Select all
MYIF=192.168.1.1
ip interface $MYIF
show ip interface $MYIFIf you wish to block variable expansion, because for instance you wish to enter a password that contains the dollar sign, you may do so, as explained above, using single quotes.
But first, functions!
I am going to touch on functions very quickly because I will use a function to demonstrate how various dollar sign variables can be used.
A function is a piece of code that you can reuse after creating it (it does not run during its creation). It can take parameters and return a diagnostic value.
Let's imagine that you spend most of your day creating new VLANs and all your VLANs share most of their parameters. It would be nice to have a command that can be re-used without specifying these parameters every time.
To create a function, type its name followed by a pair of parenthesis and an opening curly brace.
To complete the function definition, enter a closing curly brace:
Code: Select all
function myvlans()
{
}
You will then be able to run this function by entering its name:
Code: Select all
myvlansThese variables represent parameters passed to a function ("positional parameters")
If you write a Bash function e.g. "myvlans" and wish to handle parameters in the function, you will need to use those guys.
For instance:
Code: Select all
function myvlans()
{
vlan $1
}
myvlans 5This will create vlan 5.
$#
Now, you may wish to make this function a little smarter; for instance it should be able to handle cases when the user forgets to pass a parameter.
Code: Select all
function myvlans()
{
if [ $# -lt 1 ]; then
echo "You need to provide a parameter"
else
vlan $1
fi
}
myvlansThis will display an error message because $#, which represents the number of arguments that were passed to the function, is less than ("-lt") one.
$@ or $*
You may also wish to handle all the parameters at once. This is what this little guy provides.
Code: Select all
function myvlans()
{
vlan "$@"
}
myvlans 5 6 7Let's imagine, for a minute, that VLAN's syntax let you create as many VLANs as you desires, in one statement. This would be the correct way to pass all our arguments to the command.
shift
VLAN does not accept multiple VLAN ids as described in the previous paragraph. How can we go through our parameters list then?
Code: Select all
function myvlans()
{
while [ "$1" != "" ]; do
vlan $1
shift
done
}
myvlans 5 6 7Now, your script will create each VLAN using the "vlan" command. Every parameter will end up being seen as "parameter 1" thanks to the "shift" command.
"shift" moves ('shift') all the positional parameters down by one, every time it is invoked.
Therefore, with three parameters as in our above example:
$1="5", $2="6", $3="7"
Code: Select all
shift$1="6", $2="7"
Code: Select all
shift$?$1="7"
This is great but wouldn't it be smarter for us to check that a vlan was successfuly created before moving on to the next one?
We can check for that using the previous command's return code, stored in $?
Code: Select all
function myvlans()
{
while [ "$1" != "" ]; do
vlan $1
if [ $? -ne 0 ]; do
echo "Error!"
return 1
done
shift
done
}
myvlans 5 6 7If "vlan $1" returned a value other than "0" which traditionally denotes success in the Unix world, the script complains and returns immediately.
$_ (dollar sign, underscore)
This little guy represents the most recently used parameter.
For instance:
Code: Select all
vlan 5
no vlan $_Adding user interaction
Say you would like for your script to ask a few questions and use your answers.
Use the "read" command to read user input. Here's how:
Code: Select all
function myvlans()
{
echo -n "Enter VLAN id: "
read vlanid
if [ "$vlanid" -eq "" ]; do
echo "You did not enter a VLAN id! I am so confused..."
return 1
fi
vlan $vlanid
}In conclusion, the "read" command is the user-based equivalent to "variable_name=value"
Q: What keyboard shortcuts are available?
(*) Backward/Forward history search mode
Let’s say that your history contains these lines:
Code: Select all
show vlan
show vlan 5
date
show vlan 1Typing <Ctrl-R>sh will display “show vlan 1”
Typing <Ctrl-R> will display “show vlan 5”
Typing <Ctrl-S> will display “show vlan 1”
Typing <Ctrl-J> will let you start editing the latter command.
(**) Repeating a command
Let’s say you wish to move the cursor to the end of the next third word:
Typing Alt-3 Alt-F will do the trick.
More shortcuts
There are more shortcuts that you could use but I did not mention them here because they are quite complex to master; they are mostly a programmer’s friend.
The “other” mode
As if this wasn’t enough information to memorize, this set of commands matches the so-called “Emacs” mode. An alternate, incompatible set of commands known as “vi” mode is also available.
Further reading
Here is a list of external resources that address various shell-related topics more in depth:
Quoting: difference between single quotes and double quotes
http://muffinresearch.co.uk/archives/20 ... d-strings/
Quoting: a synthetic view
http://bash.cyberciti.biz/guide/Quoting
Bash scripting for beginners
http://www.linuxconfig.org/Bash_scripting_Tutorial
Bash scripting for power users
http://tldp.org/LDP/abs/html/
Bash history management
http://www.catonmat.net/blog/the-defini ... e-history/