This post introduces the powerful but risky Background Scripts in ServiceNow

 What is a Background Script?

1 – Introduction

It is a utility in ServiceNow to run scripts in the background, which is useful for mass creations, updates, and deletions of records.  It is also greatly helpful in troubleshooting records and running complex scripts to find information.  They can do complex operations in a short amount of time.

The person who has the “admin” role can use Background script.

A background script is generally used when you should run a script for a one time action, or when Admins need to run any cleanup jobs.

Converting the background script to a scheduled script on demand gives more control. In addition, you can also review the code later if required, which is not possible in a background script.

2 – Disadvantage

A disadvantage of a background script is that it doesn’t have any formatting and syntax checking. You just type raw text,  if there is an error you will only realise after the execution.

3 – The Need for Background Scripts

In ServiceNow, you can get around using background scripts by using these other methods

  • Manually creating, updating, or deleting records
  • Using the List Editor
  • Importing Data to create, update, or delete records

However, that is not the most efficient way to update data in certain cases.  It might not be feasible to use the list editor to update 200K records or make a CSV file to update the records.  Sometimes a background script can be created in minutes that solves the issue.

4 – How to find the Scripts – Background Utility

  1. Login as an Admin User
  2. Elevate your security privileges to security_admin. Click the Lock icon next to your name on the title bar
  3. Click the security_admin checkbox and click ok. The Lock icon is now unlocked
  4. Go to System Definition > Scripts – Background.  The Scripts – Background Utility appears.
    Background Scripts in ServiceNow

        WARNING: Background Scripts are powerful

With great power comes great responsibility. (Uncle Ben, Spiderman)

Example

Scenario: Admin needs a fast way to test server-side scripts without creating problem in the instance.

Solution: Background script is server side of JavaScript executor

Warning: This can be dangerous and may even crash the entire instance.

We can try:

Building a script to disable some users:

disableUsers();

function disableUsers(){

//query active user records with first name b

var users= new GlideRecord(“sys_user”);

users.addQuery(“first_name,” “STARSWITH”, “b”);

users.addActiveQuery();

users.query();

gs.print(“User query: “ + users.getEncodedQuery() + “ = “ + users.getRowCount());

  while (users.next()) {

 //deactivate user

users.active =false;

//users.update();

gs.print(users.getDisplayValue() + “ was disabled”);

}

}

Due to the possible risks, there is not too much information available from ServiceNow for background scripts. Essentially, ServiceNow doesn’t really want you to run Background Scripts if you are not experienced with them.

Chicken and Egg?

How do you get experience if you don’t try them right?  Well, there are demo ServiceNow instances and your development ServiceNow instances.  Be sure to try your Background scripts carefully before attempting on a Production ServiceNow instance.

5 – How to Avoid Disaster

Remember how I told you a few paragraphs back about how powerful background scripts are?  I really mean this, They can cause: destroyed data, revoked access, or even system shutdown.

A couple points to help you avoid unknown disasters with Background Scripts

5.1. Bad Syntax

If you are doing a glide record query and your query is not designed correctly, ServiceNow javascript will ignore the query and not produce an error.  Here is an example:

Working Script: Find a CI

findCI();

function findCI(){

grCI = new GlideRecord(‘cmdb_ci’);

grCI.addQuery(‘name’,’=’,’SAP WEB03′);

grCI.query();

while (grCI.next()){

gs.print(‘CI Found: ‘+grCI.name);

}

}

Bad Script: Accidentally Finds all CIs

findCI();

function findCI(){

grCI = new GlideRecord(‘cmdb_ci’);

grCI.addQuery(‘sys_name’,’=’,’SAP WEB03′);

grCI.query();

while (grCI.next()){

gs.print(‘CI Found: ‘+grCI.name);

}

}

In the bad script the column name in the cmdb_ci is not sys_name, it is name. This is an honest mistake, but since that column doesn’t exist ServiceNow will ignore the query and return all records.  If I was doing a delete or update statement in the background script, this would not be good.

5.2.  RowCount and Comment Out Update Statement

If you are doing an update statement in your background script.  Comment out your update statement and add a RowCount statement until you are sure it is ok.  Here is an example:

Update CI Script

updateCI();

function updateCI(){

grCI = new GlideAggregate(‘cmdb_ci’);

grCI.addQuery(‘name’,’=’,’SAP WEB03′);

grCI.addAggregate(‘COUNT’);

grCI.query();

gs.print(‘grCI Query: ‘ + grCI.getEncodedQuery() + ‘ = ‘ + grCI.getRowCount());

if (grCI.next()){

var counter = grCI.getAggregate(“COUNT”);

gs.print(counter);

//grCI.update;

}

}

With this example, it will return how many rows are going to be updated before you update.

Script Results:

[0:00:00.005] Script completed: script

*** Script: grCI Query: name=SAP WEB03 = 1

When you ready to run that script and it is going to update the right number of rows, uncomment out the update line and run again.

5.3. Use the gs.print or gs.log statements

In #2 above, used a gs.print statement to print the rowcount of the query.  However you can also use gs.log to print the results to the Script Log.  gs.log is nice if you have a log-running query.  However whichever one you pick, they are both helpful to troubleshoot issues with your script or with just general troubleshooting

5.4. Use setWorkflow(false) and autoSysFields(false)

When you are mass updating records with a background script, sometimes you don’t want to run the business rules/workflow on every record you updated or have your name and the last updated time be when you updated it.  Here is an example on how to avoid this:

updateCI();

function updateCI(){

grCI = new GlideRecord(‘cmdb_ci’);

grCI.addQuery(‘name’,’=’,’SAP WEB03′);

grCI.query();

gs.print(‘grCI Query: ‘ + grCI.getEncodedQuery() + ‘ = ‘ + grCI.getRowCount());

while (grCI.next()){

grCI.asset_tag=’ServiceNowELITE.com’;

grCI.setWorkflow(false); //Do not run business rules

grCI.autoSysFields(false); //Do not update system fields

grCI.update;

}

}

In the example above the setWorkflow and autoSysFields statements avoid those workflow and autoSysFields from being run or updated.  This is really needed in cases when you are updating tasks and the last updated time affects an sla or the tasks that have a lot of business rules on them you want to ignore.