Keeping with my theme of consistent SAS 9.4 Grid posts I’m back with a quick fix for users with Python 3-only Linux environments. You might find yourself in this situation if you were on / updating to a Rocky Linux 9 (and RHEL 9) environment where Python 2 is no longer supported.
Due to SAS Grid Manager’s “gridStart.py” and “gridStop.py” scripts being written in Python 2, with accompanying Python 2 libraries and syntax, you’d receive errors running on RHEL 9. This issue has been addressed in the new SAS 9.4M9 release with updates to these control scripts but requires a manual fix to previous SAS versions.
gridStart.py and gridStop.py are automatically generated upon install of a SAS Grid environment using user inputs from the SAS Deployment Wizard. This means the scripts are custom-made to fit the deployment (some variables like hostnames and directory paths are swapped around for user-entered deployment site info). Once properly created, they can respectively handle the starting and stopping of the SAS Workload Orchestrator process on your grid host(s).
gridStart.py:
Our first fix to gridStart.py will be to change out the “commands” module for the new “subprocess” module. Subprocess boasts a higher level of security as well as greater error handling, and fixes a file-opening consistency bug on windows that “commands” had (thanks to a reliance on wrapper functions for os.popen). You can read more about the change in the Python 2 and Python 3 docs if you’re interested.
Due to the syntax of the newer “subprocess” module, the gridStartCommand must be split into two sections to pass into our subprocess function later.
Python 2 syntax:
##************************************************************
import json
import sys
import commands
import os
# # Create the command that will start the grid on the host #
gridStartCommand = "\"sgmg.sh start > /dev/null 2>&1\""
Python 3 syntax:
##************************************************************
import json
import sys
import subprocess
import os
#
# Create the command that will start the grid on the host
#
gridStartCommand = "sgmg.sh"
gridStartCommandPt2 = ["start", ">", "/dev/null", "2>&1"]
In Python 3 we got a change to the “raw_input” function from Python 2, renaming it to “input”. Python 2 had its own function called “input” but it evaluated whatever you entered as a python expression, which could lead to security vulnerabilities. Lucky for us, we’re in the clear security-wise with “input” in Python 3. Read more about the change here.
Python 2 syntax:
#
# Get command line parameters
#
...
if (len(gridSharedDir) == 0):
gridSharedDir=raw_input("Grid Shared Directory: ")
Python 3 syntax:
#
# Get command line parameters
#
...
if (len(gridSharedDir) == 0):
gridSharedDir=input("Grid Shared Directory: ")
Python 3 allows you to specify file encoding when selecting a file with open(), which eliminates the need to specify a decoding method manually. Also, file() in Python 2 was simply an alias for the open() function, and has since been deprecated. As such, the JSON file handling portion of the script has to be modified.
Python 2 syntax:
#
# Read in and parse the master state JSON
#
jsonFile = file(masterStateFile, "r")
state = json.loads(jsonFile.read().decode("utf-8-sig"))
Python 3 syntax:
#
# Read in and parse the master state JSON
#
jsonFile = open(masterStateFile, "r", encoding="utf-8-sig")
state = json.loads(jsonFile.read())
Our last change to gridStart.py is the biggest one and includes some error handling to go along with the invocation of our newly imported subprocess module. Here is where we join together the “gridStartCommand” that was split into two pieces earlier.
Python 2 syntax:
#
# Start the service on every host in the JSON
#
for host in state['hosts']:
print("Starting " + host['name']);
command = "ssh " + host['name'] + gridCommand
status, output = commands.getstatusoutput(command)
print(host['name'] + ": " + output);
Python 3 syntax:
#
# Start the service on every host in the JSON
#
for host in state['hosts']:
print("Starting " + host['name'])
command = ["ssh", host['name'], gridCommand] + gridStartCommandPt2
result = subprocess.run(command, universal_newlines=True, stdout =
subprocess.PIPE, stderr=subprocess.STDOUT)
output = result.stdout
print(host['name'] + ": Output - " + output)
errors = ""
if result.stderr is not None:
errors = result.stderr
print(host['name'] + ": Errors - " + errors)
gridStop.py:
There’s not a lot to change for this script! Here we simply need to update “raw_input” to “input”, like we did in gridStart.py.
Python 2 syntax:
#
# Create grid URL from configuration properties
#
...
if (len(user) == 0):
user=raw_input("Username: ")
if (len(pwd) == 0): pwd=getpass.getpass("Password: ")
if (len(gridURL) == 0):
gridURL=raw_input("Grid URL: ")
Python 3 syntax:
#
# Create grid URL from configuration properties
#
...
if (len(user) == 0):
user=input("Username: ")
if (len(pwd) == 0):
pwd=getpass.getpass("Password: ")
if (len(gridURL) == 0):
gridURL=input("Grid URL: ")
Your Python 2-less SAS Grid environment will thank you. This blog was made to hopefully popularize a fix for releases prior to 9.4 M9 grid environments, that operate on more recent Linux distributions such as RHEL 9. While you don’t necessarily need the Python scripts to start SAS Workload Orchestrator daemons, they’re nicer than the alternative: starting each daemon separately on each grid host. However, some terminal softwares allow you to execute commands on multiple machines at once, which could be a quicker fix depending on how comfortable you are with the features of your environment.
Related Links:
SAS Help Center: Using Control Scripts
36.16. commands — Utilities for running commands — Python 2.7.18 documentation
subprocess — Subprocess management — Python 3.13.2 documentation
Find more articles from SAS Global Enablement and Learning here.
Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!
The rapid growth of AI technologies is driving an AI skills gap and demand for AI talent. Ready to grow your AI literacy? SAS offers free ways to get started for beginners, business leaders, and analytics professionals of all skill levels. Your future self will thank you.