scriptRunner will run all scripts within a folder that you specify.

April 27, 2014 ยท View on GitHub

#!/usr/bin/python

scriptRunner will run all scripts within a folder that you specify.

Useful for LaunchAgents and running multiple scripts at user login.

Thanks to Greg Neagle for an example of how to do this and Nate Walck for v1

Copyright 2014 Allister Banks (see end for Apache license blurb)

import optparse import os import subprocess import plistlib import datetime import sys import stat import logging import logging.handlers

Set your organizations reverse domain in the 'once' check file:

orgPlistString = "org.my.scriptRunnerOnce.plist"

logging.basicConfig(level=logging.WARN)

logr = logging.getLogger('scriptRunner')

handler = logging.handlers.SysLogHandler(address = '/private/var/run/syslog')

logr.addHandler(handler)

Possible ways to get called command output to syslog:

def sh(cmd):

return Popen(cmd,shell=True,stdout=PIPE,stderr=PIPE).communicate()[0]

output = (sh("/usr/local/sbin/mgmt/everyTest.sh"))

# logr.critical(sh('echo "foo"'))

logr.critical("SCRIPTRUNNER: %s", output)

TODO: - check return code from called script

- send stderr/out to (sys)log

Further:

- default wrap shell scripts with 'bash -x'? 'once' only?

- separate, permanent log(s) for called script/scriptRunner itself?

(issue is launchA can't write to /var/log, & /Users/Shared or /tmp aren't ideal)

maybe setup tee'd output to ~/Lib/Logs when subprocess calls?

def checkPermsAndRun(script): st = os.stat(script) mode = st.st_mode if script.lower().endswith(('.rb', '.py', '.sh')): # only run if executable AND everyone write access is NOT set # as explained succinctly here: http://stackoverflow.com/a/1861970 if (mode & stat.S_IXOTH) and not (mode & stat.S_IWOTH): subprocess.call(script, shell=True) else: print script + " is not executable or has bad permissions"

def main(): p = optparse.OptionParser() p.set_usage("""Usage: %prog [options]""") p.add_option('--once', '-o', dest='runOnce', help="""Directory of scripts to run only once.""") p.add_option('--every', '-e', dest='runEvery', help="""Directory of scripts to run every time.""")

options, arguments = p.parse_args()
if not (options.runOnce or options.runEvery):
    print "Please choose a frequency and the path to a folder containing (1 or more) scripts"
    p.print_help()
    sys.exit(1)

# Check to see if passed options are a directory that exists or not
for path in (options.runOnce, options.runEvery):
    if path is not None:
        if not os.path.isdir(path):
            sys.exit(path + " is not a directory")

if options.runEvery:
    for script in os.listdir(options.runEvery):
        checkPermsAndRun(os.path.join(options.runEvery, script))

if options.runOnce:
    runOncePlist = os.path.expanduser("~/Library/Preferences/") + orgPlistString
    try:
        runOncePlistValues = plistlib.readPlist(runOncePlist)
    except IOError:
        runOncePlistValues = {}
    for script in os.listdir(options.runOnce):
        if script in runOncePlistValues:
            print os.path.join(options.runOnce, script) + " already run!"
        else:
            checkPermsAndRun(os.path.join(options.runOnce, script))
            runOncePlistValues[script] = datetime.datetime.now()
            plistlib.writePlist(runOncePlistValues, runOncePlist)

if name == 'main': main()

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

http://www.apache.org/licenses/LICENSE-2.0

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.