Programmatically "reset printing system" via command line

haircut
Contributor

Our users routinely snarf things up playing around with printers, trying to add home printers or change queue names to work with Printopia; or things just get hosed.

I'm working on a Self Service policy to blow away the printers and re-add all those scoped to the user. When I do this manually, I use the "Reseting printing system..." option accessed by right-clicking the printer list in the System Preferences pane.

Is there a way to invoke this action from the command line so that I could script it? In 10.4 and 10.5 there was a PrintingReset.sh script in the Printer Setup Utility bundle, but that tool is gone in later releases.

I'm aware that I can simply kill the queues via lpadmin and reset cupsd.conf, but I think the OS is doing a bit more to "fully" reset cups. If you watch the system log, clicking "reset printing system" invokes printtool (found at /System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A/printtool) but specifically what it's doing is a bit out of my depth.

Any thoughts?

24 REPLIES 24

vadanx
Contributor

You can actually reuse that script PrintingReset.sh and it still seems to work for me, just import it to Admin.

A

vadanx
Contributor

You can actually reuse that script PrintingReset.sh and it still seems to work for me, just import it to Admin.

A

jacob_salmela
Contributor II

I have had success with this:

sudo launchctl stop org.cups.cupsd
sudo rm /etc/cups/cupsd.conf
sudo cp /etc/cups/cupsd.conf.default /etc/cups/cupsd.conf
sudo rm /etc/cups/printers.conf
sudo launchctl start org.cups.cupsd

Stop CUPS

sudo launchctl stop org.cups.cupsd

Remove CUPS config file

sudo rm /etc/cups/cupsd.conf

Restore the default config by copying it

sudo cp /etc/cups/cupsd.conf.default /etc/cups/cupsd.conf

Remove the printers

sudo rm /etc/cups/printers.conf

Start CUPS again

sudo launchctl start org.cups.cupsd

yan1212
Contributor

Jacob's solution is good but if you just want to blow away the printers this one liner will do it for you:

lpstat -p | cut -d' ' -f2 | xargs -I{} lpadmin -x {}

You could paste it into the 'Send a unix command' field in the advanced tab and create a self service policy if that's all you need.

haircut
Contributor

Thanks all! As I said in OP:

I'm aware that I can simply kill the queues via lpadmin and reset cupsd.conf, but I think the OS is doing a bit more to "fully" reset cups.

Since the "printtool" binary is called when doing a reset through the GUI, I was more curious if anyone was familiar with leveraging that specific tool.

jacob_salmela
Contributor II

I found a link that details what Reseting the print system does. It mentions printtool and you might be able to script each portion of it:

http://reviews.cnet.com/8301-13727_7-57583652-263/what-does-the-reset-print-system-routine-in-os-x-d...

haircut
Contributor

@jacob_salmela Perfect! Exactly what I was looking for!

I think the permissions updates are probably key to the full reset. Running a permission check after a user installs the printer vendor bloatware usually finds a bunch of problems in /Library/Printers.

jacob_salmela
Contributor II

No problem! It looks like a fun project to dive into. If you do come up with something, please post it on this thread and mark it as answered.

kraigschroth
New Contributor III

This is what I've used:

#!/bin/sh
#resetprinting.sh

shopt -s nullglob

for file in /etc/cups/ppd/* ; do path=${file%.ppd}; name=${path##*/}; lpadmin -x ${name};
done

I have then a menu set for all the printers to use lpadmin to drop in the correct printers.

johnnasset
Contributor

I use this in a shell script. Really just deletes all printers vs a system reset.

lpstat -p | awk '{print $2}' | while read printer
do
echo "Deleting Printer:" $printer
lpadmin -x $printer
done

rmanly
Contributor III

@kraigschroth

I've actually found this method to be problematic in certain cases where printer names don't correspond to PPDs.

I've switched to using the output of lpstat like @johnnasset or like the following, there was a reason I went with -v and not -p but I don't remember it now...

#!/bin/bash

while read -r _ _ printer _; do
    lpadmin -x "${printer/:}"
    # bash4
    # lpadmin -x "${printer::-1}"
done < <(lpstat -v)

https://github.com/rmanly/scripts/blob/master/mac_mgmt/removal/rm_all_printers.bash

rmanly
Contributor III

@johnnasset

You should really do the while loop like this instead of creating a pipeline.

while read printer; do
    echo "Deleting Printer:" $printer
    lpadmin -x $printer
done < <(lpstat -p | awk '{print $2}')

"Using a pipe to send find's output into a while loop places the loop in a SubShell and may therefore cause problems later on if the commands inside the body of the loop attempt to set variables which need to be used after the loop; in that case, see FAQ 24, or use a ProcessSubstitution like:"

http://mywiki.wooledge.org/BashFAQ/001
http://mywiki.wooledge.org/ProcessSubstitution

donmontalvo
Esteemed Contributor II

@kraigschroth wrote:

This is what I've used:
#!/bin/sh
#resetprinting.sh

shopt -s nullglob

for file in /etc/cups/ppd/ ; do
path=${file%.ppd};
name=${path##/};
lpadmin -x ${name};
done
I have then a menu set for all the printers to use lpadmin to drop in the correct printers.

+1...although we've never used this part:

shopt -s nullglob

Don

--
https://donmontalvo.com

TreeMan
New Contributor

Can anybody help me with my thread?

https://jamfnation.jamfsoftware.com/discussion.html?id=11626#responseChild66813

Thanks!

cainehorr
Contributor III

I use a very similar approach. I also have a slight twist on dealing with networked printers in an Active Directory environment where Macs are not bound.

One might be inclined to just use whatever printers appear in the Bonjour search results but as we all know, Bonjour is a form of multicast, therefore it won't span subnets and you'll only see printers that are on the same subnet that the system is connected to.

For further reading: According to RFC2365 ( http://tools.ietf.org/html/rfc2365 ) and IANA’s multicast assignments ( http://www.iana.org/assignments/multicast-addresses/multicast-addresses.txt ), 224.0.0.0/24 is reserved for link-local multicast. This means that a multicast packet address to anything in the range of 224.0.0.0 – 224.0.0.255 should never cross between IP subnets.

This approach might work for an environment with a flat network, but when you start working with multiple subnets, then things get complicated.

So you might feel inclined to go the route of attaching your unbound Macs directly to the printer's IP address using the LPD protocol.

Again, in some situations, this works fine.

Now let's throw another curve ball... let's say you have VPN... and your admins don't want to set up the required routes from the Macs in question to the printers, not to mention we're back to the multi-subnet thing. No Bonjour, DNS resolution might be janky, certain protocols and ports might be blocked... blah blah blah...

So what's a poor tech to do???

Well, we could push for policy change within IT... Perhaps we push to bind Macs to AD (GACK! What a horrid thought). That would allow us to see all AD resources being broadcast. But isn't there another way?

Why yes! There is! I thought you'd never ask!

Server Message Block, or SMB for short!

Keep your AD binding tied to your Windows platforms. I'll take my unbound Macs and use SMB, thank you very much!

[code]
#!/bin/sh

echo "######################################################################"
echo "# DELETING OLD PRINTER CONFIGURATIONS"
echo "######################################################################"
lpstat -p | awk '{print $2}' | while read printer
do echo "Deleting:" $printer lpadmin -x $printer
done

echo
echo "######################################################################"
echo "# RESETTING CUPS PRINTING SERVICES"
echo "######################################################################"
sudo launchctl stop org.cups.cupsd
sudo rm /etc/cups/cupsd.conf
sudo cp /etc/cups/cupsd.conf.default /etc/cups/cupsd.conf
sudo rm /etc/cups/printers.conf
sudo launchctl start org.cups.cupsd

echo
echo "######################################################################"
echo "# ACQUIRE USER'S ACTIVE DIRECTORY CREDENTIALS"
echo "######################################################################"
read -p "User's Active Directory Username: " ADUserName

# HP LaserJet 4250
# IP Address: xx.xx.xx.xx
echo "HP LaserJet 4250 - 1st Floor"
lpadmin -p "HP-1st-Floor" -L "1st Floor, San Francisco, CA, USA" -E -v smb://"server.com/HP-1st-Floor" -U $ADUserName -P "/Library/Printers/PPDs/Contents/Resources/HP LaserJet 4250.gz" -o printer-is-shared=false

# SHARP MX-3110N
# IP Address: xx.xx.xx.xx
echo "SHARP MX-3110N - 1st Floor"
lpadmin -p "SHARP-1st-Floor" -L "1st Floor, San Francisco, CA, USA" -E -v smb://"server.com/SHARP-1st-Floor" -U $ADUserName -P "/Library/Printers/PPDs/Contents/Resources/SHARP MX-3110N.PPD.gz" -o printer-is-shared=false -o Option5=2TrayDrawer

echo
echo "######################################################################"
echo "# STARTING CUPS WEB INTERFACE"
echo "######################################################################"
echo

sudo cupsctl WebInterface=yes
open http://localhost:631/printers/

exit
[/code]

This will reset the print queue and configure the printers.

WARNING: You'll get errors if the appropriate drivers aren't installed.

When a user goes to print, they will be prompted for their AD credentials. They can save said credentials to the Keychain for future use (this will need to be addressed if the AD password is changed).

This method allows the unbound Mac to print to any printer that the Windows print server is broadcasting, regardless of subnets. VPN may still take some negotiating depending on how much of a Net Nazi the admins are. YMMV!

Best regards!

P.S. If you have an MFP or other printer type that has all kinds of additional options, you might be hard pressed to determine how to configure the -o flag for your scripts. So here's an AWESOME helper script that I found that does the heavy lifting for you...

http://www.brunerd.com/blog/2012/03/13/getting-and-setting-ppd-options-via-command-line-for-use-with...

Kind regards,

Caine Hörr

A reboot a day keeps the admin away!

jperkins01
New Contributor

06314a12b8b54cfea85c4557eff89b32
lpstat -p | cut -d' ' -f2 | xargs -I{} lpadmin -x {}

I attempt to have Self Service Policy with this in place in Files and Processes but the attached happens! How can lpadmin be unauthorized? Anyone have a simple yet effective policy for Self Service to delete all printers?

morgsdaly
New Contributor

Hello,

I have been playing with the solutions I have been reading about here to reset the printing system in Yosemite. I don't seem to be getting very far though. No matter what I run, after restart the printers are still there.

I suspect that it has something to do with the MCX caching but I have also been unable to resolve that idea.

Wondering what you guys are doing these days to reset the printing system via a script that results in an empty printer list in system preferences upon restart?

Thanks
Morgs

bpavlov
Honored Contributor

@morgsdaly How are you adding the printers? If you are using profiles I think they get reinstalled each time on restart. Here's the script I use for resetting the print job.

#!/bin/bash

#This script will reset printing system

#Stop CUPS
launchctl stop org.cups.cupsd

#Backup Installed Printers Property List
if [ -e "/Library/Printers/InstalledPrinters.plist" ]
    then
    mv /Library/Printers/InstalledPrinters.plist /Library/Printers/InstalledPrinters.plist.bak
fi

#Backup the CUPS config file
if [ -e "/etc/cups/cupsd.conf" ]
    then
    mv /etc/cups/cupsd.conf /etc/cups/cupsd.conf.bak
fi

#Restore the default config by copying it
if [ ! -e "/etc/cups/cupsd.conf" ]
    then
    cp /etc/cups/cupsd.conf.default /etc/cups/cupsd.conf
fi

#Backup the printers config file
if [ -e "/etc/cups/printers.conf" ]
    then
    mv /etc/cups/printers.conf /etc/cups/printers.conf.bak
fi

#Start CUPS
launchctl start org.cups.cupsd

#Remove all printers
lpstat -p | cut -d' ' -f2 | xargs -I{} lpadmin -x {}

exit 0

I got a lot of this from reading this CNET article and other threads on JAMFNation.

http://www.cnet.com/news/what-does-the-reset-print-system-routine-in-os-x-do/

I tried to use the printtool referenced in that article but it didn't do much. I didn't spend any more time on it, but it may be possible to use string to see if there are any commands that can be used with the tool.

morgsdaly
New Contributor

Thanks bpavlov,

I was about to build something off the back of the same article but was able to use your script instead. It may have been the way I was trying to do things but your script was ultimately the one that got me over the line.

Thanks
Morgs

MikeyD
New Contributor II

A little off-topic, but does anyone have a script to delete a specific printer from a workstation or laptop which can be utilized on Apple Remote Desktop or JAMF Casper Suite. I don't want to delete everything like being discussed here, just a specific printer.

Thanks in advance for any help.

mm2270
Legendary Contributor III

@MikeyD I believe you would want to use lpadmin -x followed by the name of the printer as it would show up when running lpstat -p
At least that's where I would start.

stevewood
Honored Contributor II
Honored Contributor II

@MikeyD you can also use a loop to remove a single printer or multiple:

lpa='/usr/sbin/lpadmin'

# loop through the printers and if found, remove
printers=($(lpstat -p | awk '{print $2}' | sed '/^$/d'))

for i in "${printers[@]}"
do

    if [[ ${i} == *"PRINTER1"* ]]; then
        ${lpa} -x ${i}
    elif [[ ${i} == *"PRINTER2"* ]]; then
        ${lpa} -x ${i}
    fi

done

Change "PRINTER1" and "PRINTER2" to be the printer names you want to remove. If you need more, just add more elif statements.

If you don't want to worry about the name of the printer, but instead want to use the IP address, you can use:

oldPrinter=`${lps} -s | grep 192.168.100.30 | awk {'print $3'} | sed s'/.$//'`
if [[ ${oldPrinter} ]]; then

    ${lpa} -x ${oldPrinter}

fi

Obviously changing the IP address to match.

howie_isaacks
Valued Contributor

Thanks @bpavlov ! This worked perfectly for me.

geebee
New Contributor II

/System/Library/Frameworks/ApplicationServices.framework/Frameworks/PrintCore.framework/Versions/A/printtool --reset -f