Skip to main content

Hi folks,



I ran across a need to add systems from a list of computer names to a static group in the JSS. Andrew Seago posted a script to add them by JSS ID, but that wasn't quite what I needed.



I also needed to get a list of systems that were not found in our JSS, since I knew this list came from a source besides Casper. I added an export function that will output to a CSV to identify systems it couldn't match. It is not case-sensitive in regards to the input list (the list I received had mixed cases).



I also had to deal with the fact that sometimes OS X will append (2) or something similar to the computer name when it thinks there is another computer with that name on the network. I'm using a wildcard search at the end of the name when I perform a lookup so those are captured. If more than one match is found, the line is skipped for safety reasons.



Anyways, I would love some input on this (it works great but if anyone else thinks it is useful and has feature requests, let me know). I know it's not super efficient because I am looking up each computer name as a separate API call, but I was more concerned about having something working in a couple hours and may perform rewrites later.



Just enter the JSS, JSSGROUPID, JSSUSER, and JSSPASS variables and you are ready to go. Please read the script notes as well.



#!/bin/bash

# Copyright 2014 by Alex Dale
# Add computers to a static group in a JSS from a plaintext list of computer names
#
# Make sure your target group is a static group and is empty, or it will be overwritten
# Input file must have one name per line.
# Usage: scriptname.sh /path/to/input/file
# Add "export" as an optional argument after input file to export a csv with failed system lookup info to /tmp/JSSFailures.csv
# Searches are performed with a wildcard at the end to catch names with (2), etc appended to the name by the OS
# Multiple matches (due to wildcard or dupe records) will be skipped, for safety
#
# Test this first on your dev JSS! I cannot account for all scenarios.

#Verify input file exists
if [ ! -f "$1" ]; then
echo "Input file not found, exiting"
exit 1
fi
IMPORTLIST=$1
EXPORTFLAG=$2
exportCSV="/tmp/JSSFailures.csv"
# Hostname of JSS
JSS=""
# Group ID for target static group
JSSGROUPID=""
# API service account credentials
JSSUSER=""
JSSPASS=""
# Start building XML for computer group, which will be uploaded at the end
GROUPXML="<computer_group><computers>"

if [ ! "$JSS" ] || [ ! "$JSSGROUPID" ] || [ ! "$JSSUSER" ] || [ ! "$JSSPASS" ]; then
echo "Required variables have not all been entered. Please validate and retry."
exit 1
fi

echo "Input file: $1"

# Read list into an array
inputArraycounter=0
while read line || [[ -n "$line" ]]; do
inputArray[$inputArraycounter]="$line"
inputArraycounter=$[inputArraycounter+1]
done < <(cat $IMPORTLIST)
echo "${#inputArray[@]} lines found"

foundCounter=0
for ((i = 0; i < ${#inputArray[@]}; i++)); do
echo "Processing ${inputArray[$i]}"
nameLookup=`curl -s -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computers/match/${inputArray[$i]}*`
sizeLookup=`echo $nameLookup | xpath //size 2>/dev/null | tr -cd [:digit:]`
if [ $sizeLookup = 1 ]; then
idLookup=`echo $nameLookup | xpath //id 2>/dev/null`
if [ "$idLookup" ]; then
GROUPXML="$GROUPXML<computer>$idLookup</computer>"
foundCounter=`expr $foundCounter + 1`
fi
echo "Match found, adding to group"
else
echo "$sizeLookup entries found, skipping."
if [ "$EXPORTFLAG" = "export" ]; then
echo "${inputArray[$i]},$sizeLookup computers matched">>$exportCSV
fi
fi
done
GROUPXML="$GROUPXML</computers></computer_group>"

echo "$foundCounter computers matched"

echo "Attempting to upload computers to group $JSSGROUPID"
curl -s -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computergroups/id/$JSSGROUPID -X PUT -HContent-type:application/xml --data $GROUPXML

If you receive "0 computers matched" "Attempting to upload computers to group x" -- With the result that no computers get added to the static group:




  • A possible solution is to ensure your input file does not contain any extensions (.txt) in the filename!


Thank you @alexjdale and @cshepp11 , for sharing this script. I was able to make half way.
Do you also have script to remove computers from static group? Please share with me if you got one ready.
I was trying to modify the given script to remove computers in it but it was deleting the static group itself.



Thank you.


@Naren Take a look at the thread Script to add a device to a computer group? for an example of how to add a computer to an existing Static Group rather than replacing the contents of the group. Following the example in that thread you can use computer_deletions instead of computer_additions to remove computers from a group instead of adding them.


Thank you @sdagley for sharing the link.
I was trying with two different scripts one to add multiple computers to static group other to remove from static group.
But when i was trying to execute the script it is adding or removing only the last entry from excel.
For example my .csv file has four computers and script is actually only reacting to the last one in it.
@cshepp11



!/bin/bash



currentuser=$(stat -f%Su /dev/console)
HostName=$(scutil --get ComputerName)
logdir="/Users/${currentuser}/Desktop/AdminExceptions.csv"



Verify input file exists



if [ ! -f "${logdir}" ]; then
echo "Input file not found, exiting"
exit 1
fi
IMPORTLIST="${logdir}"



EXPORTFLAG=€1.80



exportCSV="/tmp/JSSFailures.csv"



Hostname of JSS



JSS="jssportal.com"



Group ID for target static group



JSSGROUPID="53"
JSSGROUPNAME="AdminRightExceptions"



API service account credentials



JSSUSER="apiuser"
JSSPASS="apipwd"



Start building XML for computer group, which will be uploaded at the end



GROUPXML="<computer_group><computer_deletions>"



if f ! "$JSS" ] || | ! "$JSSGROUPID" ] || | ! "$JSSUSER" ] || | ! "$JSSPASS" ]; then
echo "Required variables have not all been entered. Please validate and retry."
exit 1
fi



echo "Input file: ${logdir}"



Read list into an array



inputArraycounter=0
while read line || | -n "$line" ]]; do
inputArraya$inputArraycounter]="$line"
inputArraycounter=$=inputArraycounter+1]
done < "$IMPORTLIST"
echo "${#inputArraya@]} lines found"



foundCounter=0
for ((i = 0; i < ${#inputArraya@]}; i++)); do
echo "Processing ${inputArraya$i]}"
nameLookup=curl -s -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computers/name/${inputArraya$i]}
sizeLookup=echo $nameLookup | xpath //size 2>/dev/null | tr -cd d:digit:]
if f "$sizeLookup" != "" ]; then
idLookup=echo $nameLookup | xpath //id 2>/dev/null
if f "$idLookup" ]; then
GROUPXML="$GROUPXML<computer>$idLookup</computer>"
foundCounter=$((foundCounter+1))
fi
echo "Match found, adding to group"
else
echo "$sizeLookup entries found, skipping."
if f "$EXPORTFLAG" = "export" ]; then
echo "${inputArraya$i]},$sizeLookup computers matched">>$exportCSV
fi
fi
done
GROUPXML="$GROUPXML</computer_deletions></computer_group>"
echo "$foundCounter computers matched"



deleting computer from casper with UUID



echo "Attempting to Delete computers from group $JSSGROUPID"
curl -s -v -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computergroups/id/$JSSGROUPID -X PUT -HContent-type:application/xml --data $GROUPXML


@sdagley any idea why its picking up only last line in the lookup, for example if I have 3 values, a, b, c in the list it will only process value c and leave other 2 items?


Hey, in order to run script in Big Sur, use xpath5.18



#!/bin/bash

# Copyright 2014 by Alex Dale
# Add computers to a static group in a JSS from a plaintext list of computer names
#
# Make sure your target group is a static group and is empty, or it will be overwritten
# Input file must have one name per line.
# Usage: scriptname.sh /path/to/input/file
# Add "export" as an optional argument after input file to export a csv with failed system lookup info to /tmp/JSSFailures.csv
# Searches are performed with a wildcard at the end to catch names with (2), etc appended to the name by the OS
# Multiple matches (due to wildcard or dupe records) will be skipped, for safety
#
# Test this first on your dev JSS! I cannot account for all scenarios.

#Verify input file exists
if [ ! -f "$1" ]; then
echo "Input file not found, exiting"
exit 1
fi
IMPORTLIST=$1
EXPORTFLAG=$2
exportCSV="/tmp/JSSFailures.csv"
# Hostname of JSS
JSS="jss.domain.com"
# Group ID for target static group
JSSGROUPID="inputyourgroupidhere"
# API service account credentials
JSSUSER="username"
JSSPASS="password"
# Start building XML for computer group, which will be uploaded at the end
GROUPXML="<computer_group><computers>"

if [ ! "$JSS" ] || [ ! "$JSSGROUPID" ] || [ ! "$JSSUSER" ] || [ ! "$JSSPASS" ]; then
echo "Required variables have not all been entered. Please validate and retry."
exit 1
fi

echo "Input file: $1"

# Read list into an array
inputArraycounter=0
while read line || [[ -n "$line" ]]; do
inputArray[$inputArraycounter]="$line"
inputArraycounter=$[inputArraycounter+1]
done < "$IMPORTLIST"
echo "${#inputArray[@]} lines found"

foundCounter=0
for ((i = 0; i < ${#inputArray[@]}; i++)); do
echo "Processing ${inputArray[$i]}"
nameLookup=`curl -s -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computers/name/${inputArray[$i]}`
sizeLookup=`echo $nameLookup | xpath5.18 //size 2>/dev/null | tr -cd [:digit:]`
if [ "$sizeLookup" != "" ]; then
idLookup=`echo $nameLookup | xpath5.18 //id 2>/dev/null`
if [ "$idLookup" ]; then
GROUPXML="$GROUPXML<computer>$idLookup</computer>"
foundCounter=`expr $foundCounter + 1`
fi
echo "Match found, adding to group"
else
echo "$sizeLookup entries found, skipping."
if [ "$EXPORTFLAG" = "export" ]; then
echo "${inputArray[$i]},$sizeLookup computers matched">>$exportCSV
fi
fi
done
GROUPXML="$GROUPXML</computers></computer_group>"

echo "$foundCounter computers matched"

echo "Attempting to upload computers to group $JSSGROUPID"
curl -s -k -u $JSSUSER:$JSSPASS https://$JSS:8443/JSSResource/computergroups/id/$JSSGROUPID -X PUT -HContent-type:application/xml --data $GROUPXML

Reply