Preflight And Postflight Scripts

DCoobs edited this page Jan 24, 2018 · 11 revisions

Information about munki preflight and postflight scripts


managedsoftwareupdate supports optional preflight and postflight scripts. A preflight script is executed before managedsoftwareupdate does the bulk of its work. A non-zero exit code causes managedsoftwareupdate to abort its run. A postflight script is executed just before managedsoftwareupdate exits. It's a good place to analyze the logs and report errors to a central location.


Both the preflight and postflight scripts must reside in the same directory as managedsoftwareupdate.

A preflight script must be named "preflight" and have no extension. It must be marked as executable. A non-zero exit code causes managedsoftwareupdate to exit.

A postflight script must be named "postflight" and have no extension. It must be marked as executable.

Both scripts are passed a single parameter - the "runtype". This allows the script to distinguish between the various "modes" in which managedsoftwareupdate runs. These runtypes have not yet been formally defined, and may change in the future. Here are the current runtypes:

  • auto - this corresponds to the periodic run of managedsoftwareupdate, currently controlled by /Library/LaunchDaemons/com.googlecode.munki.managedsoftwareupdate-check.plist

  • logoutinstall - this runtype occurs when a user has chosen to install updates using Managed Software and is logging out and installing (because the items to be installed require a logout or restart). This always happens at the login window.

  • checkandinstallatstartup - designed for the initial bootstrapping of a machine, this runtype causes munki to do a check (and install if needed) at startup. Triggered by the existence of /Users/Shared/.com.googlecode.munki.checkandinstallatstartup This always happens at the login window.

  • installwithnologout - user has chosen to install updates without logging out.

  • manualcheck - user has launched Managed Software manually, and it is checking for updates.

  • custom - None of the above.

Note that since the pre and postflight scripts are in the same directory as managedsoftwareupdate, if they are written in python, they can easily import any of the modules in munkilib, including munkistatus, which would allow the scripts to provide user feedback in a manner similar to the other Munki tools.

The postflight script is an ideal place to parse the logs from the current managedsoftwareupdate run and forward errors or warnings to a central location, via email or a web cgi, or perhaps code that adds records to a database.

Reporting consoles

Reporting consoles like Sal and MunkiReport-PHP make use of managedsoftwareupdate preflight and postflight scripts to upload client data to their respective databases.


Here are two examples uses of preflight scripting with their own documentation on the wiki:

Here's an example of a script that emails warnings or errors to an administrator:

# encoding: utf-8
managedsoftwareupdate postflight
Created by Greg Neagle on 2010-06-02.
import sys
import os
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import formatdate
from email import Encoders
import plistlib
# Change the following as needed
mail_from = ""
mail_to = [""]
smtpserver = ""
managed_installs_dir = "/Library/Managed Installs"
def send_mail(send_from, send_to, 
              subject, text, files=[], 
    assert type(send_to)==list
    assert type(files)==list
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = ", ".join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject
    msg.attach( MIMEText(text) )
    for f in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(f,"rb").read() )
                        'attachment; filename="%s"' % os.path.basename(f))
    smtp = smtplib.SMTP(server)
    smtp.sendmail(send_from, send_to, msg.as_string())
def main():    
    report = os.path.join(managed_installs_dir, "ManagedInstallReport.plist")
    if os.path.exists(report):
        pl = plistlib.readPlist(report)
        errors = pl.get("Errors","")
        warnings = pl.get("Warnings","")
        if not (errors or warnings):
        subject = ""
        body = "The following issues were reported:\n\n"
        if errors:
            subject = "[Managed Installs errors] on %s" % os.uname()[1]
            body = body + "Errors:\n%s\n\n" % "\n".join(errors)
        if warnings:
            if not subject:
                subject = "[Managed Installs warnings] on %s" % os.uname()[1]
            body = body + "Warnings:\n%s\n\n" % "\n".join(warnings)
        body = body + "A full report is attached.\n"
        attachments = [report]
if __name__ == '__main__':


Munki 3

Managed Software Center

Command-line Tools

Munki configuration




Advanced Munki

Related tasks


Product-specific notes

Legacy Documentation

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.