Automation
Automation

Scripting How-To: Prevent Parallel Execution of SLAX Scripts

by Juniper Employee on ‎10-11-2015 10:34 AM - edited on ‎09-11-2017 05:41 PM by Administrator Administrator (1,484 Views)

Overview

 

Sometimes you have the requirement to prevent that multiple instances of a single SLAX script run in parallel. This might be the case, when an event-script is called by interval (e.g. every 60 seconds) but was not finished before next interval.

 

In this article I would like to explain one proposal to prevent multiple parallel executions of a SLAX script.

 

This proposal is based on the concept of PID files known from Unix/Linux. At the beginning of the script it looks for the existence of the corresponding PID file in TMPFS. If this file is not present it creates a new one with the own PID within or reads the PID from file if present. This PID from file will be compared with the output of show system processes extensive to check if the script is still running.

 

Code

 

version 1.1;
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 jutils = "http://jutils/";

import "../import/junos.xsl";

template junoscript() {
/* open connection */
var $connection = jcs:open();

var $running_pid = jutils:running( $connection, $script );
if ( $running_pid ) {
<xsl:message terminate="yes"> "terminate script because another instance with pid " _ $running_pid _ " is still running";
}

/*
* ... YOUR CODE HERE ...
*/

/* close connection */
var $closed = jcs:close ( $connection );
}

function jutils:running( $connection, $name ) {
/* function to check if another instance of this script is still running
*
* :param connection: connection handle
* :param name: name used to identify the script
* :return: pid of running instance or false
*/
mvar $running = false();

var $pid = <pid> $junos-context/pid;
var $pid_filename = "/mfs/var/tmp/" _ $name _ ".pid";
var $pid_file = document( $pid_filename );

if ( not( jcs:empty( $pid_file//pid ) ) ) {
var $processes_rpc = { <command> "show system processes extensive"; }
var $processes := jcs:execute( $connection, $processes_rpc );
var $processes_lines = jcs:break-lines( $processes );

for-each( $processes_lines ) {
if ( jcs:regex( "^[[:blank:][:space:]]*" _ $pid_file//pid _ "[[:blank:][:space:]]+.*cscript.*", . )[1] ) {
set $running = true();
}
}
}
if ( $running ) {
result $pid_file//pid;
} else {
<xsl:document method="xml" href=$pid_filename append="no"> {
copy-of $pid;
}
result false();
}
}

  

Example Output

 

USER@HOST> file show /mfs/var/tmp/test.slax.pid
<?xml version="1.0"?>
<pid>47590</pid>

USER@HOST> show system processes extensive | match "^47590.*cscript$"
47590 root 1 8 0 7792K 4684K nanslp 0:00 0.00% cscript

USER@HOST> op test
error: terminate script because another instance with pid 47590 is still running