def populateList(self, sender): self.selected.clear() self.w.list._removeSelection() item = self.pathList.titleOfSelectedItem() for i in range(len(self.w.list)): del self.w.list[0] thisItem = {} image = None id = os.getuid() systemWarning = "You should not edit or remove existing system's daemons. These jobs are required for a working macOS system." if item != 'Active Daemons': if item == 'User Agents': homedir = os.path.expanduser('~') path = homedir + '/Library/LaunchAgents' # If the folder doesn't exist in the user folder, create it try: os.listdir(path) except: os.mkdir(path) elif item == 'Global Agents': path = '/Library/LaunchAgents' elif item == 'Global Daemons': path = '/Library/LaunchDaemons' elif item == 'System Agents': path = '/System/Library/LaunchAgents' self._warning(self, systemWarning, "showSystemWarning") elif item == 'System Daemons': path = '/System/Library/LaunchDaemons' self._warning(self, systemWarning, "showSystemWarning") items = [] files = os.listdir(path) count = 0 for file in files: if file.endswith('.plist'): file = file.replace('.plist', '') try: pid = launchd.LaunchdJob(file).pid except: pid = False if launchd.LaunchdJob(file).exists() and pid != None: image = NSImage.imageNamed_(NSImageNameStatusAvailable) elif launchd.LaunchdJob(file).exists() and pid == None: image = NSImage.imageNamed_( NSImageNameStatusPartiallyAvailable) else: image = NSImage.imageNamed_(NSImageNameStatusNone) state = True thisItem['image'] = image thisItem['name'] = file self.w.list.append(thisItem) count += 1 self.w.counter.set(str(count) + ' Jobs')
def _loadUnloadDaemon(self, sender, command): self.w.list.scrollToSelection() name = self.selected['name'] path = self.selected['file'] if bool(launchd.LaunchdJob(name).exists()): try: subprocess.call( ['launchctl', 'unload', '%s' % path], cwd='/', shell=False, universal_newlines=False) except: return else: try: subprocess.call( ['launchctl', 'load', '%s' % path], cwd='/', shell=False, universal_newlines=False) except: return self.populateList(self)
def plist_launch_write(label, program_arguments, scope): plist = dict( Label=label, ProgramArguments=program_arguments.split(), RunAtLoad=True, KeepAlive=True, ) job = launchd.LaunchdJob(label) fname = launchd.plist.write(label, plist, scope) launchd.load(fname)
def uninstall(label): ''' Utility function to remove a .plist file and unload it :param label: job label ''' if launchd.LaunchdJob(label).exists(): fname = launchd.plist.discover_filename(label) launchd.unload(fname) os.unlink(fname)
def agent_to_menu_item(agent) -> rumps.MenuItem: ag = plistlib.readPlist(agent) label = ag['Label'] ar = rumps.MenuItem("") aj = launchd.LaunchdJob(label) exist = aj.exists() if exist: pid = aj.pid status = aj.laststatus if pid == -1 and status == 0: ar_title = NSAttributedString.alloc().initWithString_attributes_( label, b_attr) ar._menuitem.setAttributedTitle_(ar_title) insert_unload_reload(ar, aj) ar.add( rumps.MenuItem("Start", callback=lambda x: launchctl("start", label))) insert_log_menu_items(ar, ag) ar.add("Idle") ar.add("No Errors") elif pid > 0 and status == 0: ar_title = NSAttributedString.alloc().initWithString_attributes_( label, g_attr) ar._menuitem.setAttributedTitle_(ar_title) insert_unload_reload(ar, aj) ar.add( rumps.MenuItem("Stop", callback=lambda x: launchctl("stop", label))) insert_log_menu_items(ar, ag) ar.add(f"Running ({pid})") ar.add("No Errors") elif status != 0: ar_title = NSAttributedString.alloc().initWithString_attributes_( label, r_attr) ar._menuitem.setAttributedTitle_(ar_title) insert_unload_reload(ar, aj) ar.add( rumps.MenuItem("Start", callback=lambda x: launchctl("start", label))) insert_log_menu_items(ar, ag) ar.add("Stopped") ar.add(f"Error ({status})") else: ar.title = label sub_load = rumps.MenuItem( title="Load", callback=lambda x: launchd.load(f"{USER_AGENTS}/{label}.plist")) ar.add(sub_load) insert_log_menu_items(ar, ag) ar.add("Unloaded") return ar
def test_launchd_lazy_constructor(self): # we assume that com.apple.Finder always exists and that it is always # running and always has a laststatus. Hmmmm. label = "com.apple.Finder" job = launchd.LaunchdJob(label) self.assertTrue(job.exists()) self.assertFalse(hasattr(job, '_pid')) self.assertFalse(hasattr(job, '_laststatus')) self.assertEqual(None, job._properties) job.refresh() self.assertNotEqual(None, job._pid) self.assertNotEqual(None, job._laststatus) self.assertNotEqual(None, job._properties) job = launchd.LaunchdJob(label) self.assertTrue(job.exists()) self.assertNotEqual(None, job.pid) self.assertNotEqual(None, job.laststatus) self.assertNotEqual(None, job._properties) # let's do the same with something invalid: label = "com.apple.Nonexistant-bogus-entry" job = launchd.LaunchdJob(label, 1, 2) self.assertEqual(1, job.pid) self.assertEqual(2, job.laststatus) self.assertFalse(job.exists()) self.assertRaises(ValueError, job.refresh) # even though refresh() was called, the object remains unchanged: self.assertEqual(1, job.pid) self.assertEqual(2, job.laststatus) self.assertFalse(job.exists()) # also test "None": label = "com.apple.Nonexistant-bogus-entry2" job = launchd.LaunchdJob(label, None, None) self.assertEqual(None, job.pid) self.assertEqual(None, job.laststatus)
def main(): myplist = dict( Disabled=False, Label="testlaunchdwrapper_python", Nice=-15, OnDemand=True, ProgramArguments=[ "/bin/bash", "-c", "sleep 1 && echo 'Hello World' && exit 0" ], RunAtLoad=True, ServiceDescription="runs a sample command", ServiceIPC=False, ) import time label = myplist['Label'] job = launchd.LaunchdJob(label) if not job.exists(): print("'%s' is not loaded in launchd. Installing..." % (label)) install(label, myplist) while job.pid is not None: print("Alive! PID = %s" % job.pid) job.refresh() time.sleep(0.2) else: if job.pid is None: print("'%s' is loaded but not currently running" % (job.label)) else: print("'%s' is loaded and currently running: PID = %s" % (job.label, job.pid)) while job.pid is not None: print("Alive! PID = %s" % job.pid) job.refresh() time.sleep(0.2) print("Uninstalling again...") uninstall(label) return 0
def job(self): """The launchd.LaunchdJob for this LaunchAgent.""" if self.is_loaded: return launchd.LaunchdJob(self.label) else: return None
def is_loaded(self): """ Boolean indicating whether the configuration file for this LaunchAgent has been loaded. """ return launchd.LaunchdJob(self.label).exists()
if launchd.LaunchdJob(label).exists(): fname = launchd.plist.discover_filename(label) launchd.unload(fname) os.unlink(fname) myplist = dict(Label="com.example.launched.datewriter", Disabled=False, KeepAlive=True, RunAtLoad=True, Program=__file__, ProgramArguments=["/bin/bash", "-c", "python3", __file__], ServiceDescription="Test for launchd", SartInterval=10) label = myplist['Label'] job = launchd.LaunchdJob(label) if not job.exists(): print("'%s' is not loaded in launchd. Installing..." % (label)) install(label, myplist) else: if job.pid is None: print("'%s' is loaded but not currently running" % (job.label)) else: print("'%s' is loaded and currently running: PID = %s" % (job.label, job.pid)) choice = input("Uninstall? [y/n]: ") if choice == "y": print("Uninstalling...") uninstall(label) #Reads back queued launchd jobs