############################################################################################
Scripting
############################################################################################
Moshell supports the use of variables and logical constructs.
These can be used directly from the command line or within moshell command files.
***************************************
6.0- Preset Variables
***************************************
The following variables are set immediately after moshell startup:
$moshelldir ---> path to the moshell directory
$gawk ---> path to gawk
$ipaddress ---> IP address to the node that moshell is connected to
$moshell_version ---> the moshell version
$logdir ---> path to the moshell_logfiles/logs_moshell directory
$tempdir ---> path to the directory containing all temporary files for this moshell session. Gets deleted at the end of the session.
$uname ---> output from the "uname -a" command, showing the operating system of the workstation running moshell.
The following variables are set after the MOM has been parsed:
$momversion ---> the MOM version of the node (eg: RNC_NODE_MODEL_E_5_3, MGW_NODE_MODEL_R3_9_0)
$cellomomversion ---> the CPP MOM version (eg: 3.3, 4.3, 5.1, etc) of the node
$momdocnumber and $momdocrevision --> the document number and revision of the MOM (eg: 15554-AXD10503/1 , rev: Z1)
These variables can be handy to have when a script needs to know what SW revision is running in the node or what kind of node it is.
The following variables are set after running certain MO commands:
$cppversion --> the CPP version of the node, according to the information in the current UpgradePackage.
$nr_of_mos --> the number of MOs that were printed on screen by the last run of the pr/st/get/prod/fro/set/del/acc commands.
$nr_of_mos_ok --> the number of MOs that were successfully operated upon by the last run of the set/del/acc commands.
$command_result --> set after running the cr/pcr/pset/trun commands. Possible values: 0 for success, 1 for failure.
$returncode --> set after running any moshell command. Possible values: 0 for success, 1 for failure.
$action_result --> set after running the acc command. Contains the return value of the action.
$nr_of_alarms --> the number of active alarms on the node. Set after the last run of the "al" command.
$nr_of_cvs --> the number of CV:s that exist on the node, is set after the last run of the "cvls" command.
$nr_of_scanners --> the number of scanners printed by the last run of the pst/pgets/pdel/pbl/pdeb commands.
$nr_of_counter_instances --> the number of counter instances printed by the last run of the pgetsn command.
$moncommand --> the command to start the monitor client after having run the "mon" command.
$background_pid --> the process id of a process started into background from moshell command line, eg: l $moncommand > $logfile &
The following variables are set after running the commands bp/bo:
$coremp_pos --> the positions of the core MPs, eg: 001000:001100
$coremp_type --> the board types of the core MPs, eg: GPB53:GPB53
The following variables are set after running one of the l+/u+/u- commands.
$logfile ---> the logfile that is currently open. Set immediately after executing the "l+" command, stays set even after "l-" and will only be reset the next time a new logfile is open with "l+"
$undologfile ---> the logfile used by the undo command. Set immediately after executing the "u+/u+s" command, stays set even after "u-" and will only be reset the next time a new undo mode is started with "u+/u+s".
$undocommandfile --> the command file that can be used to undo the commands that were run between "u+/u+s" and "u-". Set immediately after executing the "u-" command.
$undodelcommandfile --> the file containing the delete commands. Only applicable to simulated undo mode "u+s".
The following variable is set after having logged on to the node via telnet/ssh or ftp/sftp.
$password
The contents of the variable can not be printed, it will only show if it's empty or not. By setting this variable to empty (by doing: $password = ), this will force moshell to check the password again. Useful in case the password has changed on the node during the moshell session.
The following variable is set after running the "pv" command.
$nr_of_vars
This variable indicates the number of scripting variables that were printed in the last "pv" printout. By using "pv" together with a filtering pattern (eg: pv $table), it is possible to find out the number of variables that had matched the pattern, for instance the number of elements in a hashtable.
The following variable is set after using the functions "readfile" or "testfile".
$nr_of_lines
After using the function "testfile", this variable is set to 0 if the file does not exist and to 1 if the file exists.
After using the function "readfile", this variable is set to 0 if the file does not exist and to the number of liens in the file if the file exists. The difference between testfile and readfile is that testfile won't actually read the file, it will just check if the file exists whereas readfile will test the file, then read it.
Example1:
$lineContent = testfile(/path/to/myfile)
if $nr_of_lines = 0
l echo "File not found!"
return
fi
Example2:
$lineContent = readfile(/path/to/myfile)
if $nr_of_lines = 0
l echo "File ot found!"
return
fi
for $lineNumber = 1 to $nr_of_lines
if $lineContent[$lineNumber] ~ thispattern
print We found it! The line is $lineNumber.
return
fi
done
Example: list all scripting variables currently set
>> pv
$logdir = /home/eanzmagn/moshell_logfiles/logs_moshell
$momversion = RNC_NODE_MODEL_E_5_3
$moshelldir = /home/eanzmagn/tools/moshell
$cellomomversion = 4.3.1
$gawk = /home/eanzmagn/tools/moshell/gawk
$ipdaddress = 10.1.128.17
$moshell_version = 6.1
$nr_of_mos = 1
$password = *******
***************************************
6.1- Variable assignment
***************************************
A variable value can be assigned in six ways, see below.
A variable can also be unassigned, using the "unset" command.
By using the command "unset small", all variables are unset, except:
- the "system" variables ($gawk, $ipaddress, $password, $moshell_version, $moshelldir, $logdir, $momversion, $cellomomversion)
- the "global" variable(s) (ie: assigned with the ":=" sign, instead of "=").
By using the command "unset all", all variables are unset except the "system" variables.
NOTE !!! It is always good practice to unset a variable as soon as it is not needed anymore since having too many variables defined slows down the processing of the command line. It is also good to do "unset all" at the beginning and end of a command file (and before doing the "return" command) in order to avoid interference from un-needed variables. See the script examples in moshell/commonjars/scripts.
To print all currently assigned variables, use the command "pv" (used to be called "printvars").
To just print one variable, type:
>> pv <pattern> (where the pattern matches the variable(s) to print)
Or:
>> print $variable
a) from the command line
The variable to be assigned is on the left side of the equal sign and the value is on the right side. Each element must be separated by spaces. Example:
>> $i = 3
>> $node = RNC
>> $password = (set the password to an empty value, will force moshell to check the password again).
b) at moshell startup, using the "-v" option
In this case, the "$" sign should be omitted (otherwise it gets interpreted by the unix shell)
Example:
>> moshell -v upmo=CXP9011008_R1A03,ftpserv=10.1.0.16,secure_shell=1,secure_ftp=1 rnc34
In this case, we can see that scripting variables ($upmo and $ftpserv) and user variables (secure_shell and secure_ftp) have been mixed in the same statement. This is ok because any variable that is not recognised as a user variable will be treated as a scripting variable.
b) from the following commands: get, fro, ip2d/d2ip, h2d/d2h, uv.
The mo-filter and attribute-filter must be specified, then comes the redirection sign (">"), then the variable name.
If several attributes are printed, only the last attribute value gets assigned into the variable.
Examples:
>> get 0 productName > $nodeType (result: $nodeType = RBS3202)
>> get ethernetlink ipaddress > $ipaddress (result: $ipaddress = 10.1.128.17)
>> get configurationversion currentupgrade > $currentUp (result: $currentUp = UpgradePackage=CXP9011123_R12F)
>> get $currentUp administrativedata > $swRev (result: $swRev = Struct{5} >>> 1.productNumber = CXP9011123 >>> 2.productRevision = R12F etc.)
>> lfro subrack=ms,slot=1,pluginunit=1$ ^r > $froid (result: $froid = 0)
>> d2ip -4127129085 > $ip_addr (result: $ip_addr = 10.1.2.3)
>> h2d 0xa > $res (result: $res = 10)
>> uv ^credential > $credential (result: /home/ericsson/moshell/commonjars/host.p12)
c) using an arithmetic operation
The following numeric operations are supported:
+ addition
- substraction
* muliplication
/ division
% modulo (returns the remainder of an integer division operation)
Examples:
>> $i = 1 (result: $i=1)
>> $i = $i + 1 (result: $i=2)
>> $j = $i * 3 (result: $j=6)
>> $k = $i * $j (result: $k=12)
>> $l = $i / $j (result: $l=0.333)
>> $m = $k % 5 (result: $m=2)
Note: Only one operation per line is allowed. A space must exist between each element of the operation. There cannot be more than two members in the operation (ie: $i = $j + $k ==> OK. But $i = $j + $k + $l ===> NOTOK)
d) using output from a unix command:
The unix command must be surrounded by back-quotes (`). Variables can be used within the unix command.
Example1:
>> $date = `date +%y%m%d-%H%M` (result: $date = 040930-1745)
>> get ethernetlink ipaddress > $ipaddress (result: $ipaddress = 10.1.128.17)
>> $logfile = $ipaddress_$date.log (result: $logfile = 10.1.128.17_040930-1745.log)
>> l+m $logfile (open a logfile, don't display anything on the screen)
>> te log read
>> l- (close logfile)
>> $errors = `grep -c ERROR $logfile` (result: $errors = the number of ERRORs found in the logfile)
>> l rm $logfile (remove the logfile)
Example2: making a cv that has the same name as the current startable cv but the last digit is incremented by 1
>> lt configurationversion
>> get configuration startable > $startable (result: $startable = RBS3045_P2.1.5_CU3_A_01)
>> $cvname = `$gawk -v cvname=$startable 'BEGIN { print gensub(/..$/,"",1,cvname) sprintf("%02s",substr(cvname,length(cvname)-1)+1) }'`
>> cvms $cvname (result: $cvname = RBS3045_P2.1.5_CU3_A_02)
e) using result from a unix command:
If the built-in function "system" is used instead of the back-quotes (`) then the exit code of the unix command is saved to the variable (instead of its output).
Example:
>> $result = system(cp $file1 $file2) (result: 0 if the copy was successful, or some other number if the copy failed)
f) using string manipulation
The following string operations are supported: concatenation and substitution/replacement.
The concatenation is performed by juxtaposing the strings.
Syntax for concatenation: $var = string1string2string3 (the strings are concatenated without space in between)
or $var = string1 string2 string3 (the strings are concatenated with spaces in between)
The substitution/replacement is performed using the "-s" switch to specify the string to substitute and the "-r" switch to specify the string it should be replaced with. If the "-r" switch is not used, then the string will be replaced by nothing. If the "-g" switch is specified, then all instances of the string to substituted, otherwise, only the first instance.
Syntax for substitution/replacement: $var = originalString -s stringToSubstitute [-r stringToReplaceItWith [-g ] ]
Regular expressions can be used in the string manipulations.
Examples:
>> $var = abc_defabc ghi
>> $var1 = $var -s abc (result: $var1 = _defabc ghi , only first instance of "abc" was replaced)
>> $var2 = $var -s \x020 (result: $var2 = abc_defabcghi , the space sign was removed)
>> $var3 = $var -s abc -g (result: $var3 = _def ghi , all instances of "abc" were replaced)
>> $var4 = $var -s abc -r xyz (result: $var4 = xyz_defabc ghi , first instance of "abc" was replaced with "xyz")
>> $var5 = $var -s abc -r xyz -g (result: $var5 = xyz_defxyz ghi , all instances of "abc" were replaced with "xyz")
>> $var6 = $var -s a.*c -r xyz (result: $var6 = xyz ghi , the regular expression "a.*c" was replaced with "xyz")
>> $var7 = $varABC$var6 (result: $var7 = abc_defabc ghiABCxyz ghi , the three strings "$var", "ABC" and "$var6" have been concatenated)
>> $var8 = $var ABC $var6 (result: $var8 = abc_defabc ghi ABC xyz ghi , there are spaces in between the three strings)
Note: if more advanced string manipulation is needed, it is always possible to use an external program such as gawk to do the string manipulation. See example 2 in paragraph d) above.
g) using output from a predefined function
Currently, the following functions exist:
* fdn(proxy) ---> input is the proxy id, output is the FDN
* ldn(proxy) ---> input is the proxy id, output is the LDN
* rdn(proxy) ---> input is the proxy id, output is the RDN
* motype(proxy) ---> input is the proxy id, output is the MO type
* proxy(string) ---> input is the LDN or FDN (NOT RDN!), output is the proxy id
* readinput(sring) ---> input is a prompt that should appear on the screen, so that the user can input an answer which will then be assigned to the variable.
* readinputsilent(sring) ---> same as readinput() but without echoing the user input. useful for entering passwords.
* readfile(file) ---> input is a filename. Each line of the file is assigned into an element of the hashtable into which we have assigned the result of the function. If the file is not found, the variable $nr_of_lines is set to 0, otherwise it is set to the number of lines in the file. Note, this should not be used on large files as it will slow down things very much.
* testfile(file) ---> input is a filename. If the file is not found, the variable $nr_of_lines is set to 0, otherwise it is set to 1.
* split(string) --> The string is split into the array specified on the left side of the equal sign (see example below). The separator used to split the string can be specified in the variable "$split_separator". By default it is a space. If the $split_separator has been changed and needs to be reset to the default value, just run the command "unset $split_separator". The number of elements in the array is stored in the variable $split_last
* mod2nr(string) --> Convert a RncModule name into a module number. Eg: mod2nr(MS-6-1) returns 1061 , mod2nr(ES-1-24-0) returns 241 .
* check_ip_contact(ipaddress,port) --> check connectivity to a given ip address and tcp port. Returns 0 if ok, or a value greater than 0 if not ok.
Example1:
>> lt iublink
>> ma iub iub
>> for $mo in iub
$mordn = rdn($mo)
if $mordn ~ 1023
lcc $mordn
lbl $mordn,
fi
done
Example2:
>> $var = readinput(Please confirm [y/n]: )
>> if $var !~ ^y
return
fi
Example3:
>> $table = readfile(/path/to/myfile)
>> for $lineNumber = 1 to $nr_of_lines
print $table[$lineNumber]
$word = split($table[$lineNumber])
if $word[1] ~ ^#
$nr_of_comments = $nr_of_comments + 1
fi
unset $word
unset $table[$lineNumber]
done
(Note: by unsetting the entry we've just read - provided we don't need it anymore - will make things faster)
Example4:
Logging in to an unknown node with moshell "-n" option (no ip connectivity check) and checking the type of node
The loop is intended to keep checking if the node happens to be down at the time of the check.
>> for 10
>> $var80 = check_ip_contact($ipaddress,80)
>> $var9830 = check_ip_contact($ipaddress,9830)
>> $var4912 = check_ip_contact($ipaddress,4192)
>> if $var4192 = ok
>> uv comcli=21
>> uv username=expert
>> $password = expert
>> break
>> else if $var9830 = ok
>> uv comcli=11
>> uv username=root
>> $password = root
>> break
>> else if $var80 = ok
>> uv comcli=0
>> break
>> else
>> wait 30
>> $i = $i + 1
>> fi
>> done
h) Example
The purpose of the little moshell script below is to make a customized CV name like: date_nodeType_swRev
>> cvls
>> $date = `date +%y%m%d` (result: $date = 040930)
>> get 0 productName > $nodeType (result: $nodeType = RBS3202)
>> $nodeType = $nodeType -s RBS (result: $nodeType = 3202)
>> get configurationversion currentupgrade > $currentUp (result: $currentUp = UpgradePackage=CXP901913%2_R12N)
>> get $currentUp administrativedata > $swRev (result: $swRev = Struct{5} >>> 1.productNumber = CXP901913/2 >>> 2.productRevision = R12N >>> 3.productName = CXP901913%2_R12N ....)
>> $swRev = `gawk -v currentsw="$swRev" 'BEGIN{ swrev=gensub(/\r|\n/,"","g",currentsw) ; print gensub(/^.*Revision = | >>> 3.product.*$/,"","g",swrev) }'` (result: $swRev = R12N)
>> cvms $date_$nodeType_$swRev (result: cvms 040930_3202_R12N )
***************************************
6.2- Hashtables (arrays)
***************************************
The index and the value of the hashtable can be a variable, a constant, or a mix of both.
All variable assignment methods described in chapter 6.1 apply for assigning values into hashtables as well.
To print a hashtable, do: pv <table>
More examples on how to use hashtables are described in 6.4.
***************************************
6.3- If/Else constructs
***************************************
The if statement must be followed by a condition. The comparison operator of the condition must be surrounded by spaces.
Zero or more "else if" statements can be used after the "if" statement.
Zero or one "else" statements can be after the "if" or "else if" statements.
The end of the if/else structure must be specified with a "fi" statement.
Each statement must be on its own line and can be followed by one or more commands.
Several conditions can be combined, using the logical AND (&&), or the logical OR (||).
Any number of AND/OR can be put on a line but NOT BOTH on the same line.
Grouping conditions with brackets is NOT supported.
The "return" command can be used to exit from the command file in case a certain condition is met.
Type "h return" for more information on how to use this command.
Syntax examples:
a) if <condition>
command1
command2
fi
b) if <condition1> || <condition2>
command1
command2
else
command3
fi
c) if <condition> && <condition2> && <condition3>
command1
else if <condition4>
command2
else
command3
fi
A condition can use the following comparison operators:
= equals
~ matches
!= is not equal to
!~ does not match
> greater than
< less than
>= greater or equal than
<= less or equal than
The words around the operator can be either a variable or a single word but NOT a string containing spaces or a concatenation of a variable and string.
Following conditions are syntaxically correct:
if $var1 = $var2
if mystring ~ $var
if 10 > 3
if $i < 2
Following conditions are NOT syntaxically correct and will return unexpected results:
if mystring_$var1 ~ $var2
if mystring is this ~ your string
A condition can also just contain one variable, in which case it will check if the variables exists.
Examples:
>> if $var ---> check if the variable $var exists
>> get 0 productname > $nodeType
>> if $nodeType ~ 3202 || $nodeType ~ 3104
get feeder attenuation
set feeder attenuation 4
else if $nodeType ~ 3101
get feeder attenuation
set feeder attenuation 16
else
get feeder attenuation
fi
***************************************
6.4- For constructs
***************************************
The parameter to the "For" construct can be:
a) "ever" : to repeat the loop an infinite number of times
b) <numberOfIterations> : to repeat the loop a specific number of times
c) $mo in <moGroup> : to run the body of the loop on each MO of the specified moGroup. MO groups are created with the "ma" command, type "h ma" for info.
d) $board in <boardGoup> : to run the body of the loop on each board of the specified board group. Board groups are created with the "ba" command, type "h ba" for info.
f) $var in $table : for each iteration of the loop, $var will cycle through the index values of the hashtable $table
g) $var = $start to $stop : $var is assigned every integer value between $start and $stop. $start and $stop can be variables or constants but must be an integer. If $start is smaller than $stop than the order will be ascending, otherwise it will be descending.
The end of the "for" structure must be specified with a "done" statement.
The "wait" command can be used in the body of the loop to specify a delay to wait in between each iteration.
The delay can be in seconds, minutes, hours, or even ROP periods. (Type "h wait" for info.)
Do not use the "sleep" command as this will result in hanging if the loop is aborted.
The loop can be aborted any time by typing ctrl-z , then "touch <stopfile>", then "fg".
The <stopfile> path is shown in the window title bar. Type "h ctrl-z" for more info about aborting.
The break command can be used within the loop to exit from the loop.
Syntax examples:
a) for ever
command1
command2
done
b) for <numberOfTimes>
command1
wait <numberOfSeconds>
done
c) for $mo in <moGroup>
get $mo <attribute> > $variable
$variable1 = ....
set $mo <attribute> $variable1
etc...
done
d) for $board in <boardGroup>
bl $board
facc $board restart 0 1
wait 10
deb $board
lhsh $board vii
done
e) for $proxy in $proxytable
bl $proxy
st $proxy
deb $proxy
st $proxy
get $proxy operational > $opstate
if $opstate != 1
break
fi
done
f) for $var = $maxproxy to $minproxy
del $var
done
for $var = 1 to 6
te e trace$min process
done
Examples:
a) checking the progress of a UP installation, every 10 seconds.
Break from the loop if the result is "1 (INSTALL_COMPLETED)", and continue with upgrade action.
Abort the command file if the result is "6 (INSTALL_NOT_COMPLETED)"
>> lt upgrade
>> acc upgradepackage=xxx nonblockinginstall
>> for ever
$return = 0
wait 10
get upgradepackage=xxx state > $upstate
if $upstate ~ ^1
break
else if $upstate ~ ^6
$return = 1
break
fi
done
if $return = 1
return
fi
acc upgradepackage=xxx upgrade
b) run a testcase 50 times
>> for 50
run testcase_3.1.1.cmd
wait 2m
done
c) increase the primaryCpichPower by 0.1 dBm on each UtranCell
>> lt ^utrancell
>> ma cell ^utrancell
>> for $mo in cell
get $mo primarycpichpower $pich
$pich = $pich + 1
set $mo primarycpichpower $pich
done
d) restart all boards in a board group
>> ba spb spb
>> for $board in spb
acc $board restart
0
1
done
e) save the fro values of all programs into a table and then restart every program
>> lma programs_on_slot_19 subrack=ms,slot=19,.*program
>> for $prog in programs_on_slot_19
$i = $i + 1
fro $prog ^res > $frolist[$i]
done
>> for $fro in $frolist
restartObj pgm $fro
done
f) restart some boards in a specific order
>> for $var = 20 to 14
$board = 00$var00
facc $board restart 0 1
done
***************************************
6.5- User-defined functions
***************************************
Users can define their own functions, using the func/endfunc construct.
If the function is called with arguments, these are assigned to the variables $1, $2, $3, etc
The variable $0 is set to the whole line contents.
Example:
1. Define the function (the function definitions can be run in a different command file)
Here we are defining a function which checks the state of the mirrored disks and returns once the disks are in sync
func check_disk_state
#if $1 is undefined or different to an integer value then we set it to 10 seconds
if $1 ~ ^[0-9]+$
$wait_interval = $1
else
$wait_interval = 10
fi
for ever
wait $wait_interval
l+om $tempdir/diskstate
lh coremp mirror s
l-
$res = `grep -c "eer Disk Status: *Valid" $tempdir/diskstate
if $res > 0
break
fi
done
endfunc
func waitforuser
$date = `date "+%Y-%m-%d %H:%M:%S"`
for ever
$reply = readinput(Waiting from [$date]. Type "y" when ready: )
if $reply ~ ^[yY]
break
fi
done
$date = `date "+%Y-%m-%d %H:%M:%S"`
print "Finished waiting at [$date]"
endfunc
endfunc
2. Call the function
Here we have made a small script which makes use of our user-defined function.
First we are running a file containing all the definitions for our user-defined functions.
(Note that the functions can also be defined within the same script, but by keeping all functions in a separate file means that several command files can use the same functions)
We have called the function check_disk_state with an argument "5" which in this case will be used as the "$wait_interval" parameter in the function
run ~/myfunctions_define.mos
for ever
check_disk_state 5
waitforuser
facc 0 manualrestart 0:i 0:i 0:s
pol
done
***************************************
6.6- Nesting
***************************************
It is possible to nest one or more if/else statement within a loop statement and vice-versa.
But it is currently not possible to nest an if/else statement within an if/else statement and a loop statement within another loop statement.
The current workaround is to put the for/if constructs into functions. See chapter 6.5 for more info on functions.
Example:
The following script starts the install, then checks the state of the install every 10 seconds.
Once the upgradepackage is installed, it starts the upgrade.
Then it checks the state again and once the upgrade is in state "awaitingconfirm", it confirms the upgrade.
$UP = upgradepackage=CXP9011123_R12F
acc $UP nonblockinginstall
for ever
wait 10
get $UP state > $state
if $state ~ ^1
break
fi
done
get $UP state > $state
if $state ~ ^1
acc $UP upgrade
fi
wait 120
for ever
wait 10
get $UP state > $state
if $state ~ ^3
break
fi
done
if $state ~ ^3
acc $UP confirmupgrade
fi
***************************************
6.7- Examples
***************************************
Example scripts can be found under moshell/commonjars/scripts and moshell/examples/scripting/
Note two types of comments can be used in scripts:
- visible comments: start with the "#" sign. These comments are printed on the screen while the script is executing.
- invisible comments: start with the "//" sign. These comments are not printed on the screen.