Adding and Removing Printers with Munki

1,605 views
Skip to first unread message

Walter Meyer

unread,
Jun 19, 2010, 10:14:15 AM6/19/10
to munki-dev
I am deploying and removing printers using Munki and I thought I would
share my workflow with everyone. I am managing printers with Munki and
not MCX because managing printers with MCX was less than ideal.

In a situation where a department or a lab gets a new shared printer
and the drivers for it aren't installed on the workstations, the
drivers have to be installed before MCX is applied to the machines to
manage the printer. If the MCX policy for the printer applies first
and points to the PPD file that doesn't exist yet, the printer is just
installed using the Generic Printer Driver. You'd think on subsequent
logins and assuming the driver was installed later the MCX policy
would refresh and re-add the printer using the proper PPD, but this
doesn't happen. :/

So to install and remove a printer using Munki this is what I did:

1. Create a postflight script for a package, this is the simple sh
script I made: http://pastebin.com/PpGfaNQc

See the comments in the script for what is going one. But basically
the script installs the printer based on the variables set at the
beginning of the script. It also generates a file based on the
parameters used to install the printer, the file is subsequently used
by Munki to determine whether the printer is installed and what
settings the printer is installed with (in case you were to update the
settings down the line the generated file's MD5 checksum would
change). The script also create a removal script that can be called
with Munki to remove the information files and the printer from the
system.

2. Run makepkginfo on your printer install package.

3. Install the package on a test workstation manually and then run
makepkginfo -f /etc/cups/printers_deployment/your_printer_name. Take
the installs key information and append it to you printer install's
pkginfo file

4. Next change the uninstall_method key in the pkginfo file to look
like so:
<key>uninstall_method</key>
<string>/etc/cups/printers_deployment/uninstalls/
your_printer_name.sh</string>

5. Finally add a requires key and reference the required driver
installation package(s) for the printer. E.g.:
<key>requires</key>
<array>
<string>Lexmark Printer Drivers</string>
</array>

Here is one of my printer install pkginfo files: http://pastebin.com/3i1htk9C

The reason I did it this way is that CUPS doesn't have any unique
files for installed printers that Munki could check as far as I could
tell.

There are some potential problems with using this method as well. If a
privileged user removes the printer manually, Munki would have no way
of knowing the printer has been removed, as it is only aware of the
printer being installed based on the file generated by the install
script. But if your user is an admin they can do anything they want
anyway.

There may be a better way to do this, but this was the best one I
could come up with. Any suggestions are welcome!

Jonathan Foerster

unread,
Jun 19, 2010, 10:34:24 AM6/19/10
to munk...@googlegroups.com
Walter,

This is very clever!

Thanks so much for sharing this!

Jonathan

> --
> You received this message because you are subscribed to the Google Groups "munki-dev" group.
> To post to this group, send email to munk...@googlegroups.com.
> To unsubscribe from this group, send email to munki-dev+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/munki-dev?hl=en.
>

Greg Neagle

unread,
Jun 19, 2010, 1:22:52 PM6/19/10
to munk...@googlegroups.com
Very nice. I like the use of the requires key to automagically install any required printer driver.

-Greg

Henri Shustak

unread,
Jun 23, 2010, 6:24:06 PM6/23/10
to munk...@googlegroups.com
Your script looks great. I think the approach to uninstall is very interesting.

You may also be interested in taking a look at PrinterSetup : <http://www.lucidsystems.org/printingworks/printersetup/>

PrinterSetup features at a glance :
- Build Apple installer packages for print queue deployment
- Bundle print drivers for automatic installation with queues.
- Individual files represent each each print queue.
- Static and dynamic print queue lists
- Pre and Post hooks allowing different queues for different users.
- Ability for multiple IT groups to manage specific groups of print queues.
- Ability to manage the creation and and removal of print queues via print queue groups.
- Ability to add and remove print queues based upon network changes
eg. Change print queue list based upon currently connected wireless access point.

There is are PrinterSetup screen casts online which provide a basic introduction into some of these features :
<http://www.lucidsystems.org/printingworks/printersetup/screencasts/>

In particular, the ability to add and remove print queues is covered in the screen cast :
"Deployment : Dynamic Configuration Based on Group Membership"

Please keep in mind that the PrinterSetup project is still in beta development.

I hope this helps.


------------------------------------
This email is protected by LBackup
http://www.lbackup.org


Nate

unread,
Jun 25, 2010, 8:27:30 AM6/25/10
to munk...@googlegroups.com
I just used your directions to setup a printer for a specific department.  Thank you very much, it worked wonderfully.  I think these directions should be added to the wiki on the google code site for future reference.  Saved me from pushing this stuff over ARD (yuck!).

Nate

Patrick McNeal

unread,
Jun 25, 2010, 9:00:10 AM6/25/10
to munk...@googlegroups.com
On Fri, Jun 25, 2010 at 8:27 AM, Nate <nate....@gmail.com> wrote:
> I just used your directions to setup a printer for a specific department.
> Thank you very much, it worked wonderfully.  I think these directions should
> be added to the wiki on the google code site for future reference.  Saved me
> from pushing this stuff over ARD (yuck!).

+1 for more wiki contributions.

From personal experience, it's an easy way to contribute back to the
project, the editor is dead simple to use and people read it. I
encourage, dare say implore, anyone that wants to support the project
to give it a try.

Walter Meyer

unread,
Jun 25, 2010, 2:33:09 PM6/25/10
to munki-dev
I'd be happy to add documentation to the wiki. I think I'd need
committer access to be able to add or edit wiki pages.

Glad it worked out well for you Nate!

Walter

On Jun 25, 9:00 am, Patrick McNeal <patrick.mcn...@gmail.com> wrote:

Gary Larizza

unread,
Jun 28, 2010, 4:40:34 PM6/28/10
to munk...@googlegroups.com
To expand on this a bit,

I took your script and ran with it.  Using a piece of software called The Luggage, I create a package that uses your script as a package preflight script and then copies a custom .ppd file to /etc/cups/ppd as our main package payload.  This will customize settings (trays, initial values, etc) for your printer.  The resultant package will ONLY work on boot-volumes (so InstaDMG'ing this package is still a no-no) and I'm testing to make sure that you can still install printers from the loginwindow.  


Thanks Walter!

--
You received this message because you are subscribed to the Google Groups "munki-dev" group.
To post to this group, send email to munk...@googlegroups.com.
To unsubscribe from this group, send email to munki-dev+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/munki-dev?hl=en.




--
Gary Larizza

Director of Technology
Huron City Schools
http://www.huronhs.com


Greg Neagle

unread,
Jun 28, 2010, 4:46:12 PM6/28/10
to munk...@googlegroups.com
A suggestion:

Add a check in the preflight script that looks something like:

if [ "$3" != "/" ]; then
# we're installing on a volume other than the startup disk
exit 0
fi

This at least prevents the preflight script from doing the wrong thing when run in a context other than the one it was designed for; that is; installing on the current startup volume.

-Greg

Gary Larizza

unread,
Jun 28, 2010, 5:22:15 PM6/28/10
to munk...@googlegroups.com
Absolutely - I normally do this but DIDN'T this time because I didn't want it considered for non-boot-volume installs.  It's been committed and is up on the site.

Harry Fike

unread,
Feb 13, 2013, 5:56:47 PM2/13/13
to munk...@googlegroups.com
I'm getting ready to start deploying printers via munki, campus wide, starting from scratch. I've successfully deployed a printer using the direction on the wiki as well as some info from here: http://techjournal.318.com/mac-os-x/configure-network-printers-via-command-line-on-macs/ 

My question is, in the time since this original post, has a better way come about to accomplish this, or, potentially, lessons learned.

Thanks,
Harry

Nick McSpadden

unread,
Feb 13, 2013, 6:09:13 PM2/13/13
to munk...@googlegroups.com
Here's how I handle printers in Munki.

1) Install the printer drivers as a standard install across all machines (for example, we use all HP Printers, so installing Apple's "HP Printers Download" pretty much covers the driver install.
2) Create a payload-free package that runs a postinstall script (thanks to Walter Suny for providing this):

#!/bin/sh

# (c) 2010 Walter Meyer SUNY Purchase College

# Script to install and setup printers on a Mac OS X system in a "Munki-Friendly" way.
# Make sure to install the required drivers first!

# Variables. Edit these.
printername="printer_name"
location="location"
gui_display_name=$location
address=$printername
driver_ppd="/Library/Printers/PPDs/Contents/Resources/HP LaserJet P2015.gz"
# Populate these options if you want to set specific options for the printer. E.g. duplexing installed, etc.
option_1="HPOption_Duplexer=True"
option_2=""
option_3=""

### Printer Install ###
# In case we are making changes to a printer we need to remove an existing queue if it exists.
/usr/bin/lpstat -p $printername
if [ $? -eq 0 ]; then
        /usr/sbin/lpadmin -x $printername
fi

# Now we can install the printer.
/usr/sbin/lpadmin \
        -p "$printername" \
        -L "$location" \
        -D "$gui_display_name" \
        -v lpd://"${address}" \
        -P "$driver_ppd" \
        -o "$option_1" \
        -o "$option_2" \
        -o "$option_3" \
        -o printer-is-shared=false \
        -E
# Enable and start the printers on the system (after adding the printer initially it is paused).
/usr/sbin/cupsenable $(lpstat -p | grep -w "printer" | awk '{print$2}')

# Create an uninstall script for the printer.
uninstall_script="/private/etc/cups/printers_deployment/uninstalls/$printername.sh"
mkdir -p /private/etc/cups/printers_deployment/uninstalls
echo "#!/bin/sh" > "$uninstall_script"
echo "/usr/sbin/lpadmin -x $printername" >> "$uninstall_script"
echo "/usr/bin/srm /private/etc/cups/printers_deployment/uninstalls/$printername.sh" >> "$uninstall_script"

# Permission the directories properly.
chown -R root:_lp /private/etc/cups/printers_deployment
chmod -R 700 /private/etc/cups/printers_deployment

exit 0

3) When creating the pkginfo, add an installcheck_script (this may be optional for you) to guarantee the printer is reinstalled if deleted:
<key>installcheck_script</key>
<string>#!/bin/bash
! /usr/bin/lpstat -a printer_queue_name
exit $?</string>

4) Change the uninstall_method to call the uninstall script:
<key>uninstall_method</key>
<string>/etc/cups/printers_deployment/uninstalls/csh_williams_cart.sacredsf.org.sh</string>

5) Now you have a printer that will check for a reinstall if it's deleted (useful if you give your users permission to manage / delete printers).

The only weakness to this approach is that if you make a change to the printer settings, the installcheck script won't do any version checking and will therefore never install the updated version.  The only way around this that I can think of is to remove the installcheck_script and let Munki use its built-in version checking to install the latest edition.  After that, you can put the script back in later.

I did this for all my printers and it makes it pretty easy to either manage their installation or offer them as optional installs.


--
You received this message because you are subscribed to the Google Groups "munki-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to munki-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
--
Nick McSpadden
Client Systems Manager
Schools of the Sacred Heart, San Francisco

Timothy Sutton

unread,
Feb 13, 2013, 7:32:37 PM2/13/13
to munk...@googlegroups.com
I did a similar thing as Nick, also using the wiki article as a basis. If you need to do more than one printer, I'd strongly suggest scripting the entire process, from one command to build the packages (if you are installing them as packages, with the benefit of having a receipt) and import them into Munki with appropriate tweaks and scripts for the pkginfos.

Not only do you eliminate errors across the few places where data is used in multiple places, but you can rapidly regenerate them if you need to make any adjustments across the entire set of printers.

Tim

Harry Fike

unread,
Feb 14, 2013, 3:02:57 PM2/14/13
to munk...@googlegroups.com
Looking at the documentation, shouldn't the uninstall key it pkginfo be changed from this:

        <key>uninstall_method</key>
        <string>/etc/cups/printers_deployment/uninstalls/printserver01_PRINTER01.sh</string>

to this:

        <key>uninstall_method</key>
        <string>uninstall_script</string>
        <key>uninstall_script</key>
        <string>/etc/cups/printers_deployment/uninstalls/printserver01_PRINTER01.sh</string>

Or is that just redundant?

When I uninstall the printer via managed_uninstalls (after installing it via managed_installs), the receipt is not being removed/forgotten, so if I try to reinstall, munki thinks the printer is already installed. If I run MSU again with the printer in the managed_uninstalls array, MSU will show "Warning: Cound not find uninstall info...", which is correct, because it can't find the uninstall script.
Here is the pkginfo for one of the printers:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>autoremove</key>
<false/>
<key>catalogs</key>
<array>
<string>production</string>
</array>
<key>description</key>
<string>Installs the Duplicating Printer in Printing Services</string>
<key>display_name</key>
<string>Printing Services Xerox DT6115</string>
<key>installer_item_hash</key>
<string>169179a1f914fab346fac15ed104cc9781442842b96528092264a6e40d437485</string>
<key>installer_item_location</key>
<string>Printers/Printing_Services_Xerox-DT6115-1.0.dmg</string>
<key>installer_item_size</key>
<integer>13</integer>
<key>minimum_os_version</key>
<string>10.7.0</string>
<key>name</key>
<string>Printing_Services_Xerox-DT6115</string>
<key>receipts</key>
<array>
<dict>
<key>filename</key>
<string>Printing_Services_Xerox-DT6115-1.0.pkg</string>
<key>installed_size</key>
<integer>0</integer>
<key>packageid</key>
<string>edu.frostburg.Printing_Services_Xerox-DT6115</string>
<key>version</key>
<string>1.0</string>
</dict>
</array>
<key>uninstall_method</key>
<string>/etc/cups/printers_deployment/uninstalls/DocuTech6115.sh</string>
<key>uninstallable</key>
<true/>
<key>version</key>
<string>1.0</string>
<key>unattended_install</key>
<true/>
<key>requires</key>
<array>
<string>XeroxPrintDriver</string>
</array>
</dict>
</plist>

Here is the postflight used by the luggage:
#!/bin/sh

# (c) 2010 Walter Meyer SUNY Purchase College
# Script to install and setup printers on a Mac OS X system in a "Munki-Friendly" way.
# Make sure to install the required drivers first!

###############################################################
# Required driver is the Xerox Universal pushed out via Munki #
#                Tested with version 2.82.0                   #
###############################################################

# Variables. Edit these.
printername="DocuTech6115"
location="Printing Services"
gui_display_name="DocuTech 6115"
address="lpd://x.x.x.x/hold"
driver_ppd="/Library/Printers/PPDs/Contents/Resources/Xerox Nuvera EA DPS.gz"
# Populate these options if you want to set specific options for the printer. E.g. duplexing installed, etc.
option_1=""
option_2=""
option_3=""

### Printer Install ###
# In case we are making changes to a printer we need to remove an existing queue if it exists.
/usr/bin/lpstat -p $printername
if [ $? -eq 0 ]; then
        /usr/sbin/lpadmin -x $printername
fi

# Now we can install the printer.
/usr/sbin/lpadmin \
        -p "$printername" \
        -L "$location" \
        -D "$gui_display_name" \
        -v "$address" \
        -P "$driver_ppd" \
        -o printer-is-shared=false \
        -E
# Enable and start the printers on the system (after adding the printer initially it is paused).
/usr/sbin/cupsenable $(lpstat -p | grep -w "printer" | awk '{print$2}')

# Create an uninstall script for the printer.
uninstall_script="/private/etc/cups/printers_deployment/uninstalls/$printername.sh"
mkdir -p /private/etc/cups/printers_deployment/uninstalls
echo "#!/bin/sh" > "$uninstall_script"
echo "/usr/sbin/lpadmin -x $printername" >> "$uninstall_script"
echo "/usr/bin/srm /private/etc/cups/printers_deployment/uninstalls/$printername.sh" >> "$uninstall_script"

# Permission the directories properly.
chown -R root:_lp /private/etc/cups/printers_deployment
chmod -R 700 /private/etc/cups/printers_deployment

exit 0

And the make file:
#
#   Copyright 2009 Joe Block <j...@ApesSeekingKnowledge.net>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#       You may obtain a copy of the License at
#
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
#
#  Luggage makefile for building a package that installs a printer.

include /usr/local/share/luggage/luggage.make

TITLE=Printing_Services_Xerox-DT6115
REVERSE_DOMAIN=edu.university
PAYLOAD=pack-script-postflight
PACKAGE_VERSION=1.0



Anything stick out?

Thanks,
Harry

Gregory Neagle

unread,
Feb 14, 2013, 3:07:30 PM2/14/13
to munk...@googlegroups.com
On Feb 14, 2013, at 12:02 PM, Harry Fike <hfi...@gmail.com> wrote:

Looking at the documentation, shouldn't the uninstall key it pkginfo be changed from this:

        <key>uninstall_method</key>
        <string>/etc/cups/printers_deployment/uninstalls/printserver01_PRINTER01.sh</string>

to this:

        <key>uninstall_method</key>
        <string>uninstall_script</string>
        <key>uninstall_script</key>
        <string>/etc/cups/printers_deployment/uninstalls/printserver01_PRINTER01.sh</string>

Or is that just redundant?

The first is correct.

The second could work, but would have to be something like:

        <key>uninstall_method</key>
        <string>uninstall_script</string>
        <key>uninstall_script</key>
        <string>#!/bin/sh
/etc/cups/printers_deployment/uninstalls/printserver01_PRINTER01.sh</string>

Because uninstall_script must be a _script_, not a file that is a script.


When I uninstall the printer via managed_uninstalls (after installing it via managed_installs), the receipt is not being removed/forgotten,

Yes. If that's important, your uninstall script should remove the receipt as well.
Or remove the receipts entirely from the pkginfo and use an installs array.

Nick McSpadden

unread,
Feb 14, 2013, 3:12:21 PM2/14/13
to munk...@googlegroups.com
That's one reason to use the installcheck_script I mentioned in Step 3 - it's a way to verify that the printer is installed without relying on the receipt.  If you don't intend to use the installcheck_script, then your point is absolutely correct, you'd need to tailor the uninstall script to remove that receipt as well.

Depending on how you want to manage the installation of these printers and whether or not your users are given permission to potentially delete them, the package receipt may not even be necessary for you and you could remove the receipts, as Greg suggests.

It's sort of a balance of compromises.  Do you want receipts + Munki version control if you add new versions of your printer script later?  Do you want a simple "is printer installed or not" check?  There are strengths and weaknesses to each approach.  I've tailored this to work best for my environment (where student accounts are in the lpoperators group), but that obviously won't necessarily be true for everyone.

Harry Fike

unread,
Feb 14, 2013, 3:15:23 PM2/14/13
to munk...@googlegroups.com
Thanks for the quick reply, I'll make the adjustments to the uninstall script to forget the receipt. I thought that munki would do that, however, I haven't used this method before.

Thanks,
Harry

Gregory Neagle

unread,
Feb 14, 2013, 3:17:28 PM2/14/13
to munk...@googlegroups.com
On Feb 14, 2013, at 12:15 PM, Harry Fike <hfi...@gmail.com> wrote:

Thanks for the quick reply, I'll make the adjustments to the uninstall script to forget the receipt. I thought that munki would do that,

Not when you specify a uninstall_method other than removepackages.

-Greg

Harry Fike

unread,
Feb 14, 2013, 3:27:23 PM2/14/13
to munk...@googlegroups.com
But what if I want my users to experience a little bit of pain if they screw with their printers!?

If I implemented both the install script you suggested as well as included the receipt, I'm guessing munki would ignore the script and just check the receipt.
I think in my setup, I will just deal with the receipt. I thought about using an installs array on /etc/cups/ppd/printer_queue, however, I'm not sure how effective that would be. Any change the user made to any setting would change the MD5, however, it would be effective to check to see if the file exists.

Harry

Harry Fike

unread,
Feb 14, 2013, 3:46:52 PM2/14/13
to munk...@googlegroups.com
And on second thought, I think I'll just use the installs array to check for the existence of the printer in /etc/cups/ppd/. Trying to coordinate the receipt name in the postflight with the receipt name in the make file will be a little cumbersome for me at the moment. I'll be slowly tackling these as they come up, so I'll eventually get to it, however, this will be an acceptable process for now (unless I am totally missing something!).

Thanks,
Harry

Gregory Neagle

unread,
Feb 14, 2013, 3:48:19 PM2/14/13
to munk...@googlegroups.com
Why not check for the existence of the uninstall script?

Sent from my iPhone

MiqViq

unread,
Feb 14, 2013, 4:21:31 PM2/14/13
to munk...@googlegroups.com
maybe an installcheck_script with:

lpstat -v | grep -qw "printer_queue_name" && (echo "Queue exists"; exit 1) || (echo "Queue does not exist"; exit 0)

-MiqViq

Jon Sehmer

unread,
Aug 27, 2014, 8:38:10 PM8/27/14
to munk...@googlegroups.com, wgm...@gmail.com
I was working on adding Printers to Munki.  The examples that everyone worked on were a great first step to reaching my goals.  I really wanted to not have to do payload free packages and instead have them as nopkg install_types.  To me it seems faster and easier to share with others.

Instead of having Munki look for a receipt, I had it look for a file in /private/etc/cups/ppds/printershortname .   Is this not a good approach to doing this?


Here's my example, it seems to be working well..

Erik

unread,
Aug 27, 2014, 8:51:01 PM8/27/14
to munk...@googlegroups.com
I do something similar to your approach and it works properly. I would suggest you also create an uninstall script as well.

Daniel Hazelbaker

unread,
Aug 27, 2014, 11:40:00 PM8/27/14
to munk...@googlegroups.com, wgm...@gmail.com
I realize this is the munki list and not the "promote your own work" list, but figured I would throw this out in case it was useful to you or anybody. I built up a set of scripts that follow the munki style for determining what to install (manifests and catalogs) in way of printers.

It basically checks if the printer is marked for install or removal. If it should be installed it checks not only if the printer is already installed but also if the make, model and uri match what it should. It also sets default printer options.


Daniel
Reply all
Reply to author
Forward
0 new messages