Script to remove printers via IP address, not name

kwoodard
Contributor III

Hello all, I have been looking for a way to remove printers via IP address for a long time. We are in the process of standardizing all our printer names and queues and want to be able to replace whatever random printer was added to a computer with the new standardized printer. What is complicating things is that there are many users that have local printers/scanners/fax hooked up to their computers. I don't want to delete those (like using the command to reset CUPS) as there are many out there and the users don't have admin capabilities to add the printer back in.

So in a nutshell... Need a way to delete a printer via IP, so I can add it back in using the properly named printer stored in JAMF.

10 REPLIES 10

PatrickD
Contributor II

You could potentially use lpstat -v to get the IP/DNS name of the device and then use that data to identify the local queue name of the printer which can then be removed using lpadmin -x <queue-name>.

kwoodard
Contributor III

This is essentially what I am doing now. But with 200+ printers and 300+ computers, that’s a lot of printers to individually track down and remove. With half of those users with their own printers, just doing a blanket nuke of the printing system is problematic. Hence me trying to remove any IP printer with its IP.

PatrickD
Contributor II

Hey @kwoodard,

Wow, thats a lot of printers! I don't envy this task.

If you know that the printers were only added by the IP and not the DNS names then you can do this just using IPs but if not, you will need to compile a list of printer IP's and any DNS names they maybe know by.

You can then package that printerIPList.txt file and deploy it to the machines.
In the same policy you can then run a script similar to this to extract the "queue names"

#!/bin/bash

## write the list of currently installed printers to a text file
lpstat -v > /tmp/installedPrinters.csv

##This will iterate over the lines in /tmp/printerIPList.txt to see if any exist in /tmp/installedPrinters.csv 
##and print the lines which includes the queue name
awk -F, '
    NR == FNR {field1[$0] = $1; next}
    {
      for (line in field1) 
        if (line ~ $0) 
          print field1[line]
    }
  ' /tmp/installedPrinters.csv /tmp/printerIPList.txt

You can further manipulate the data to just extract the queue name using awk and put that in a seperate list to iterate over for the lpadmin -x command for removal. You can also use this to determine what printers they currently have so you only install what they need.

Hope this helps, good luck!

kwoodard
Contributor III

I like where you are going with this. I’m going to give it a shot tomorrow. Will report back with my progress.

We are a college campus with many different offices and work rooms. 211 printers, 117 of them unique. For simplicity sake, I make a single driver package that I keep updated and deploy with any new installs. 4 different manufacturers... File is a bit over a gig. But it works.

PatrickD
Contributor II

Sounds like quite a feat to manage all of that!

Look forward to hearing how you go.

kwoodard
Contributor III

Yeah, lucky me. LOL. I manage all the main Mac labs on our campus and support the faculty that also use them. Minority for sure, but there are some things that are easier to do on a Mac that the PC guys are envious of.

kwoodard
Contributor III

I messed around with this a little bit today, but using ARD instead of JAMF. I was able to get all the printer names for all the computers out there. Wow, talk about variety. I have an idea on how to remove these printers, but need to have JAMF fully ready to add in the newly renamed printers to all affected computers. Once thats ready, should be set to go.

Is there a way that I can have a script check a list of all the unique printer names in a text file to delete them from CUPS on multiple machines?

something like this: lpadmin -x > /tmp/listofprinters.txt

PatrickD
Contributor II

Good to hear!

Yeah you can use a while loop. You be able to adapt this to do it.

I think you would be better off putting that loop at the end of that other script so that you only need to attempt the removal of the printers that are actually on that machine. This way you send the one script that looks for those printers and removes them in one hit.

It maybe worth not putting the output the initial script into /tmp/ (as that directory will be wiped on reboot) so that you use Jamf to reference that file to determine what printers are needed and either automatically push them down, or publish them to Self Service for that machine.

kwoodard
Contributor III

Now that is an interesting thought. Would there be a way/script that could not only reference the list of printers to be deleted, and at the same time know that since IP 169.196.X.X is a valid printer IP and has a printer already in JAMF, that it could be added in before/after the old printer is removed?

mcbratney_ian
New Contributor

We designed a script to do something similar when we discovered that Configuration Profiles will not use 3rd party printer drivers. We had a large amount of computers that needed the printers to be removed and re-added via a policy without removing personal printers. Unfortunately the name of the printer when assigned via a profiles is not consistent resulting in the need to query printers by IP address.

Below is the script we created. We deployed it via a policy. Make sure to set the script to "Before" and then add the IP addresses of the printers you want to remove in Parameter 4 with a single space in between each address. The script is smart enough to remove all printers with a matching IP to ensure duplicated printers are all removed.

In the same policy you can add printers back to the machines. As long as the entries are up to date in the JSS they will use the proper "new" names.

Hopefully this helps.

#!/bin/bash

#This script will take the IP address of printers provided by JSS Parameter 4
#and delete the printer from the computer. This script is to be used before
#applying new printers via a policy.

#Input sanitation -- Checks that parameters were provided.
if [ -z "$4" ]
  then
    echo "No arguments supplied"
    exit 1
fi


#Covert String of IPs to Array deliminated by a space
IFS=" " read -r -a PrinterIPtoRemove <<< "$4"


#Input sanitation -- Checks to ensure only IP addresses are provided
for i in $(seq 0 $((${#PrinterIPtoRemove[@]} - 1)))
do
  ip=${PrinterIPtoRemove[i]}
  if [[ $ip =~ ^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$ ]]
    then
      OIFS=$IFS
      IFS='.'
      ip=($ip)
      IFS=$OIFS
      [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 
          && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
      stat=$?
      if [[ $stat -eq 1 ]]
        then
          echo "${PrinterIPtoRemove[i]}" "is not a valid IP. Exiting"
          exit 1
        fi
  else
    echo "${PrinterIPtoRemove[i]}" "is not a valid IP. Exiting"
    exit 1
  fi
done

#Checks each IP address in array and provides all names associated with IP
for i in $(seq 0 $((${#PrinterIPtoRemove[@]} - 1)))
do
  echo "Processing IP" $((i+1))
  echo "IP:" "${PrinterIPtoRemove[i]}"
 PrinterNames=$(lpstat -v | awk -v IP="lpd://${PrinterIPtoRemove[i]}" '$4 ~ IP {print $3}' | sed 's/://g')
 #Run a delete command for each name provided
 for name in $PrinterNames
 do
   echo "Deleting" "$name"
   lpadmin -x "$name"
 done
done

exit 0