Good question, and lots of options are possible. Some options although not complete are listed below.
- The op scripts could reside on each device and be manually triggered by an operator.
- The op scripts could reside off-box and triggered by say Python for Python scripts leveraging Junos PyEz.
- The op scripts could reside off-box and be triggered by Juise for SLAX scripts.
- SLAX scripts can be hosted on Junos Space and they can be either executed locally on the Junos Space server, or again using Junos Space the SLAX scripts could be staged on the managed devices, and executed from Junos Space.
- Scripts could be triggered as part of a workflow using a variety of tools e.g. Jenkins, Ansible, Git CI/CD, NETCONF, etc.
- Scripts could be scheduled to trigger using event-options on box etc.
I did take a look to see if I had any examples to hand, the following are SLAX scripts which outputs results to screen, although it wouldn't require much change to dump the results to a file as well.
version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
ns func extension = "http://exslt.org/functions";
ns utils = "http://xml.juniper.net/utils/1.0";
import "../import/junos.xsl";
match / {
<op-script-results> {
<output> {
var $local = jcs:open();
var $commands := {
<command> "ifconfig fxp0";
<command> "netstat | grep LISTEN";
<command> "top -d 1 -m cpu";
<command> "iostat -c 5";
}
for-each ( $commands/command ) {
var $result = utils:shell-execute($local, .);
expr "\n\nCommand " _ . _ "\n";
copy-of $result;
}
expr jcs:close($local);
}
}
}
<func:function name="utils:shell-execute">
{
param $conn;
param $command;
var $rpc = {
<request-shell-execute> {
<command> $command;
}
}
var $result = jcs:execute($conn, $rpc);
if ($result/..//xnm:error) {
call rpc_failure($rpc = $result/.., $message = "Error executing shell command.");
}
<func:result select="$result">;
}
Although this version is performing shell commands leveraging the request-shell-execute RPC, it would be simple enough to replace it instead with just the <command>show command</command> RPC instead.
e.g.
version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
ns func extension = "http://exslt.org/functions";
ns utils = "http://xml.juniper.net/utils/1.0";
import "../import/junos.xsl";
match / {
<op-script-results> {
<output> {
var $local = jcs:open();
var $commands := {
<command> "show version";
<command> "show chassis hardware";
<command> "show interfaces";
<command> "show cli authorization";
}
for-each ( $commands/command ) {
var $result = utils:cli-execute($local, .);
expr "\n\nCommand " _ . _ "\n";
copy-of $result;
}
expr jcs:close($local);
}
}
}
<func:function name="utils:cli-execute">
{
param $conn;
param $command;
var $rpc = {
<command format="text"> $command;
}
var $result = jcs:execute($conn, $rpc);
if ($result/..//xnm:error) {
call rpc_failure($rpc = $result/.., $message = "Error executing CLI command.");
}
<func:result select="$result">;
}
Finally, if you required the output of the commands to be stored to disk rather than output to the screen, you can implement one of the document instructions, e.g. <exsl:document>. For example:
version 1.0;
ns junos = "http://xml.juniper.net/junos/*/junos";
ns xnm = "http://xml.juniper.net/xnm/1.1/xnm";
ns jcs = "http://xml.juniper.net/junos/commit-scripts/1.0";
ns func extension = "http://exslt.org/functions";
ns utils = "http://xml.juniper.net/utils/1.0";
ns exsl extension = "http://exslt.org/common";
import "../import/junos.xsl";
match / {
<op-script-results> {
<output> {
var $local = jcs:open();
var $commands := {
<command> "show version";
<command> "show chassis hardware";
<command> "show interfaces";
<command> "show cli authorization";
}
<exsl:document href="/var/tmp/example-file.txt" method="text" indent="yes"> {
for-each ( $commands/command ) {
var $result = utils:cli-execute($local, .);
expr "\n\nCommand " _ . _ "\n";
copy-of $result;
}
}
expr "\nCommand results saved to /var/tmp/example-file.txt\n";
expr jcs:close($local);
}
}
}
<func:function name="utils:cli-execute">
{
param $conn;
param $command;
var $rpc = {
<command format="text"> $command;
}
var $result = jcs:execute($conn, $rpc);
if ($result/..//xnm:error) {
call rpc_failure($rpc = $result/.., $message = "Error executing CLI command.");
}
<func:result select="$result">;
}
Regards