Skip to content

Instantly share code, notes, and snippets.

@foozmeat
Last active October 5, 2016 21:04
Show Gist options
  • Select an option

  • Save foozmeat/64a1aa45b9b823451a86 to your computer and use it in GitHub Desktop.

Select an option

Save foozmeat/64a1aa45b9b823451a86 to your computer and use it in GitHub Desktop.

Revisions

  1. foozmeat revised this gist Sep 10, 2015. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions softwareupdate.py
    Original file line number Diff line number Diff line change
    @@ -61,7 +61,7 @@ def value_for_key(dictionary, key):


    # First request a refresh of available udpates
    check_output(["softwareupdate", "-l"], stderr=STDOUT)
    check_output(["/usr/sbin/softwareupdate", "-l"], stderr=STDOUT)

    # Next read in the list of updates from the plist
    plist_data = check_output(('/usr/libexec/PlistBuddy', '-x', '/Library/Preferences/com.apple.SoftwareUpdate.plist', '-c', 'Print :RecommendedUpdates'))
    @@ -127,12 +127,12 @@ def value_for_key(dictionary, key):
    ignore_item = True

    if ignore_item:
    print check_output(['softwareupdate', '--ignore', package_id], stderr=STDOUT)
    print check_output(['/usr/sbin/softwareupdate', '--ignore', package_id], stderr=STDOUT)
    continue
    else:
    print "\tInstalling\n"

    install_output = check_output(['softwareupdate', '-i', package_name], stderr=STDOUT)
    install_output = check_output(['/usr/sbin/softwareupdate', '-i', package_name], stderr=STDOUT)
    if 'restart' in install_output:
    restart_required = True
    print "\tRestart Required\n"
  2. foozmeat revised this gist Sep 9, 2015. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions softwareupdate.py
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,7 @@
    # -*- coding: utf-8 -*-

    """
    Created on 9-9-2015 by James Moore (@foozmeat)
    Install software updates automatically and intelligently.
  3. foozmeat created this gist Sep 9, 2015.
    162 changes: 162 additions & 0 deletions softwareupdate.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,162 @@
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    """
    Install software updates automatically and intelligently.
    If you improve this script please send me patches.
    To get started create a JSON file called settings.json using the following format
    {
    "global": {
    "ignore": [ ],
    "reboot": { "unassisted": false }
    },
    "hosts": {
    "buildvm": {
    "ignore": [ "Command Line Tools", "Xcode" ],
    "reboot": { "unassisted": true, "unless_running": ["xcodebuild"]
    }
    },
    "ghidorah": {
    "ignore": [ "Xcode" ]
    }
    }
    }
    Packages listed in `ignore` sections are substring matched. Pre-10.10 machines will need to run this
    script with `sudo` even if the user can use sudo without a password. This script should be safe to run
    from cron - it only produces output if something happens.
    """

    from subprocess import check_output, STDOUT
    import json
    import sys
    import plistlib
    from time import sleep

    # JSON keys
    kIGNORE = 'ignore'
    kGLOBAL = 'global'
    kHOSTS = 'hosts'
    kREBOOT = 'reboot'
    kUNASSISTED = 'unassisted'
    kUNLESSRUNNING = 'unless_running'


    def value_for_key(dictionary, key):
    value = None

    try:
    value = dictionary[key]

    except KeyError:
    pass

    return value


    # First request a refresh of available udpates
    check_output(["softwareupdate", "-l"], stderr=STDOUT)

    # Next read in the list of updates from the plist
    plist_data = check_output(('/usr/libexec/PlistBuddy', '-x', '/Library/Preferences/com.apple.SoftwareUpdate.plist', '-c', 'Print :RecommendedUpdates'))
    package_list = plistlib.readPlistFromString(plist_data)

    if len(package_list) == 0:
    sys.exit(0)

    with open('settings.json') as data_file:
    settings = json.load(data_file)

    hostname = check_output(['hostname']).lower().strip()
    host_key = hostname
    print "Host: %s" % hostname

    # merge settings
    global_settings = settings.get(kGLOBAL, {})
    hosts_settings = settings.get(kHOSTS, {})

    for h in hosts_settings.keys():
    if h in hostname:
    host_key = h

    host_settings = hosts_settings.get(host_key, {})

    ignores = set(global_settings.get(kIGNORE, []))
    ignores = ignores.union(set(host_settings.get(kIGNORE, [])))

    print "Ignoring packages: %s" % ', '.join(ignores)

    global_reboot_settings = global_settings.get(kREBOOT, {})
    host_reboot_settings = host_settings.get(kREBOOT, {})

    reboot_unassisted = global_reboot_settings.get(kUNASSISTED, False)
    if kUNASSISTED in host_reboot_settings:
    reboot_unassisted = host_reboot_settings.get(kUNASSISTED, False)

    reboot_unless_running = set(global_reboot_settings.get(kUNLESSRUNNING, []))
    reboot_unless_running = reboot_unless_running.union(set(host_reboot_settings.get(kUNLESSRUNNING, [])))
    reboot_unless_running = [x.lower() for x in reboot_unless_running]

    print "Reboot unassisted: %s" % reboot_unassisted
    if reboot_unassisted:
    print "Unless running: %s" % ', '.join(reboot_unless_running)

    restart_required = False

    for package in package_list:

    ignore_item = False

    package_display_name = package["Display Name"]
    package_version = package["Display Version"]
    package_id = package["Identifier"]

    package_name = '-'.join([package_id, package_version])

    print "Found package %s\n" % package_display_name

    for i in ignores:
    if i in package_name:
    print "\tIgnoring\n"
    ignore_item = True

    if ignore_item:
    print check_output(['softwareupdate', '--ignore', package_id], stderr=STDOUT)
    continue
    else:
    print "\tInstalling\n"

    install_output = check_output(['softwareupdate', '-i', package_name], stderr=STDOUT)
    if 'restart' in install_output:
    restart_required = True
    print "\tRestart Required\n"

    print "Complete"

    if restart_required:

    if not reboot_unassisted:
    print "REBOOT REQUIRED"

    else:
    can_reboot = False

    while not can_reboot:
    process_list = check_output(['ps', '-A', '-o', 'command']).splitlines()
    process_list = [x.lower() for x in process_list]
    can_reboot = True

    for i in reboot_unless_running:
    for p in process_list:
    if i in p:
    print "Found %s, waiting to reboot" % i
    can_reboot = False
    sleep(30)

    print "REBOOTING NOW"
    check_output(['sudo', 'reboot'], stderr=STDOUT)