How to check for a launched process is loaded or not in MAC OS X from shell script? - macos

I have a launchd process to unload, the command I have used is
launchctl unload /System/Library/LaunchDaemons/costomscript.plist
it works fine if the process is already loaded. But if it is not loaded and I executed the command it gives a message saying something like no such process is loaded. So I need to have a check, if the .plist file is loaded currently then only it should be unloaded otherwise not.
How I can achieve this.. please help. Thanks!!

You can get the information about running processes with launchctl.
One possibility is querying launchd with launchctl list command.
list [-x] [label]
With no arguments, list all of the jobs loaded into launchd in three
columns. The first column
displays the PID of the job if it is running. The second column displays the last exit status
of the job. If the number in this column is negative, it represents the negative of the signal
which killed the job. Thus, "-15" would indicate that the job was terminated with SIGTERM.
The third column is the job's label.
If your plist is loaded, it should be listed, otherwise not. Also first column contains pid of the process, so you could check if the process is running, for example:
$ launchctl list |grep myprocess
600 0 org.example.myprocess.1234
There is also launchctl print command that gives detailed output about a process. Check if you can use it.
print domain-target | service-target
Prints information about the specified service or domain. Domain
output includes various properties about the domain as well as a list
of services and endpoints in the domain with state pertaining to each. Service output includes various properties of the service, including information about its
origin on-disk, its current state, execution context, and last exit status.
For example:
$ launchctl print gui/501/org.example.myprocess.1234 | grep state
state = running

Try:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$ launchctl print-disabled user/uid
$ launchctl print-disabled user/501
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
And look for "=> true" in your script.
E.g.
$ launchctl print-disabled user/501
disabled services = {
"com.apple.Siri.agent" => true
"com.apple.FileStatsAgent" => false
"com.apple.ScriptMenuApp" => true
login item associations = {
"version.com.docker.helper" => "31259"
"com.docker.helper" => "com.docker.docker"
"version.com.paragon-software.ntfs.FSMenuAppLoginItemHelper" => "15.4.59"

Related

How to cancel a curl request in a shell script [duplicate]

How do I kill the last spawned background task in linux?
Example:
doSomething
doAnotherThing
doB &
doC
doD
#kill doB
????
You can kill by job number. When you put a task in the background you'll see something like:
$ ./script &
[1] 35341
That [1] is the job number and can be referenced like:
$ kill %1
$ kill %% # Most recent background job
To see a list of job numbers use the jobs command. More from man bash:
There are a number of ways to refer to a job in the shell. The character % introduces a job name. Job number n may be
referred to as %n. A job may also be referred to using a prefix of the name used to start it, or using a substring that
appears in its command line. For example, %ce refers to a stopped ce job. If a prefix matches more than one job, bash
reports an error. Using %?ce, on the other hand, refers to any job containing the string ce in its command line. If the
substring matches more than one job, bash reports an error. The symbols %% and %+ refer to the shell's notion of the current job, which is the last job stopped while it was in the foreground or started in the background. The previous job may
be referenced using %-. In output pertaining to jobs (e.g., the output of the jobs command), the current job is always
flagged with a +, and the previous job with a -. A single % (with no accompanying job specification) also refers to the
current job.
There's a special variable for this in bash:
kill $!
$! expands to the PID of the last process executed in the background.
The following command gives you a list of all background processes in your session, along with the pid. You can then use it to kill the process.
jobs -l
Example usage:
$ sleep 300 &
$ jobs -l
[1]+ 31139 Running sleep 300 &
$ kill 31139
This should kill all background processes:
jobs -p | xargs kill -9
skill doB
skill is a version of the kill command that lets you select one or multiple processes based on a given criteria.
You need its pid... use "ps -A" to find it.
this is an out of topic answer, but, for those who are interested, it maybe valuable.
As in #John Kugelman's answer, % is related to job specification.
how to efficiently find that? use less's &pattern command, seems man use less pager (not that sure), in man bash type &% then type Enter will only show lines that containing '%', to reshow all, type &. then Enter.
Just use the killall command:
killall taskname
for more info and more advanced options, type "man killall".

How to make a simple shell script that checks if the system has a process with the name specified?

Pretty much a script that checks if the system has a process with the name specified. If it does find any of the processes, it kills all of them, reporting how many processes have been terminated, otherwise it echoes that no such process exists.
for example:
$ terminateProcess [a running cpp program]
should kill all the [given file name] processes.
Can any body get me started..
No need to make a shellscript, pkill exists for years. man pkill:
pkill will send the specified signal (by default SIGTERM) to each
process instead of listing them on stdout.
-c, --count
Suppress normal output; instead print a count of matching pro‐
cesses. When count does not match anything, e.g. returns zero,
the command will return non-zero value.
Example 2: Make syslog reread its configuration file:
$ pkill -HUP syslogd

stopping LaunchAgent when uninstalling package

I build an app which provides LaunchAgent (an small UI app with "tray" icon; let's say that defined in /Library/LaunchAgents/foo.plist.
When installing package launchctl loads this LaunchAgent description automatically and starts processes for all logged-in users. (i.e i don't have to load it using launchctl load like i have to do with LaunchDaemons).
When i uninstall package, all files - including LaunchAgent plist file in /Library/LaunchAgents are removed but processes are still running.
(i have several users logged in, so there are several instances of this agent)
Now, how should i tell root launchd to stop these processes (for unspecified number of users) when running as root ? (note, launchctl ran as root doesn't even see those agents).
(pid-files,killall more-or-less-unique-executable-name is last resort and i'm keeping these solution as last resort)
Try this:
LOGGEDUSERS=`who | grep console | awk '{ print $1 }'`
for CURRUSER in $LOGGEDUSERS
do
su -l $CURRUSER -c 'launchctl unload /Library/LaunchAgents/your.plist'
done
In my uninstaller script there is also killall -15 <app_name> after that code (just in case)

How to launch crashing (rarely) application in subprocess

I'm having python application which needs to execute proprietary application (which crashes from time to time) about 20 000 times a day.
The problem is when application crashes, Windows automatically triggers WerFault which will keep program hanging, thus python's subprocess.call() will wait forever for user input (that application has to run on weekends, on holidays, 24/7... so this is not acceptable).
If though about using sleep; poll; kill; terminate but that would mean losing ability to use communicate(), application can run from few miliseconds to 2 hours, so setting fixed timeout will be ineffective
I also tried turning on automatic debugging (use a script which would take a crash dump of an application and terminate id), but somehow this howto doesn't work on my server (WerFault still appears and waits for user input).
Several other tutorials like this didn't take any effect either.
Question:
is there a way how to prevent WerFault from displaying (waiting for user input)? this is more system then programming question
Alternative question: is there a graceful way in python how to detect application crash (whether WerFault was displayed)
Simple (and ugly) answer, monitor for WerFault.exe instances from time to time, specially the one associated with the PID of the offending application. And kill it. Dealing with WerFault.exe is complicated but you don't want to disable it -- see Windows Error Reporting service.
Get a list of processes by name that match WerFault.exe. I use psutil package. Be careful with psutil because processes are cached, use psutil.get_pid_list().
Decode its command line by using argparse. This might be overkill but it leverages existing python libraries.
Identify the process that is holding your application according to its PID.
This is a simple implementation.
def kill_proc_kidnapper(self, child_pid, kidnapper_name='WerFault.exe'):
"""
Look among all instances of 'WerFault.exe' process for an specific one
that took control of another faulting process.
When 'WerFault.exe' is launched it is specified the PID using -p argument:
'C:\\Windows\\SysWOW64\\WerFault.exe -u -p 5012 -s 68'
| |
+-> kidnapper +-> child_pid
Function uses `argparse` to properly decode process command line and get
PID. If PID matches `child_pid` then we have found the correct parent
process and can kill it.
"""
parser = argparse.ArgumentParser()
parser.add_argument('-u', action='store_false', help='User name')
parser.add_argument('-p', type=int, help='Process ID')
parser.add_argument('-s', help='??')
kidnapper_p = None
child_p = None
for proc in psutil.get_pid_list():
if kidnapper_name in proc.name:
args, unknown_args = parser.parse_known_args(proc.cmdline)
print proc.name, proc.cmdline
if args.p == child_pid:
# We found the kidnapper, aim.
print 'kidnapper found: {0}'.format(proc.pid)
kidnapper_p = proc
if psutil.pid_exists(child_pid):
child_p = psutil.Process(child_pid)
if kidnapper_p and child_pid:
print 'Killing "{0}" ({1}) that kidnapped "{2}" ({3})'.format(
kidnapper_p.name, kidnapper_p.pid, child_p.name, child_p.pid)
self.taskkill(kidnapper_p.pid)
return 1
else:
if not kidnapper_p:
print 'Kidnapper process "{0}" not found'.format(kidnapper_name)
if not child_p:
print 'Child process "({0})" not found'.format(child_pid)
return 0
Now, taskkill function invokes taskkill commmand with correct PID.
def taskkill(self, pid):
"""
Kill task and entire process tree for this process
"""
print('Task kill for PID {0}'.format(pid))
cmd = 'taskkill /f /t /pid {0}'.format(pid)
subprocess.call(cmd.split())
I see no reason as to why your program needs to crash, find the offending piece of code, and put it into a try-statement.
http://docs.python.org/3.2/tutorial/errors.html#handling-exceptions

How can you start a LaunchAgent for the first time without rebooting, when your code runs as a LaunchDaemon?

I have a LaunchDaemon. When it runs, it checks if SIMBL is installed. If SIMBL is not installed, it uses NSTask to run /usr/sbin/installer on the SIMBL.pkg.
SIMBL's postflight script then tries to run a launchctl load command to start SIMBL's LaunchAgent immediately:
sudo -u "$USER" -- /bin/launchctl load -F -S Aqua -D user "${LAUNCHD_PLIST}"
This fails, because my LaunchDaemon's NSTask environment doesn't have $USER set.
If I have my daemon detect the current user with the System Configuration framework and pass it to NSTask with setEnvironment, launchctl bugs out on me:
Bug: launchctl.c:2325 (23930):13: (dbfd = open(g_job_overrides_db_path, O_RDONLY | O_EXLOCK | O_CREAT, S_IRUSR | S_IWUSR)) != -1
I realize a daemon, by definition, should not operate in a user session. By the same token, Apple seems to recommend LaunchAgents as helper objects for LaunchDaemons, to do that user session work. Is there any way to get such an agent up and running immediately?
I have all the .plists in the right places (they start running after a reboot, the next time launchctl does its regular loading) so my first thought was to just tell launchctl to reload. But all the code to do that is commented out in launchctl.c:
// { "reload", reload_cmd, "Reload configuration files and/or directories" },
...
* In later versions of launchd, I hope to load everything in the first pass,
* then do the Bonjour magic on the jobs that need it, and reload them, but for now,
* I haven't thought through the various complexities of reloading jobs, and therefore
* launchd doesn't have reload support right now.
Oh how launchd drives me crazy....
To cut to the chase, after much study and experimentation, this is how I do it on 10.5+:
# If possible, tell launchd to start the LaunchAgent. This will fail on 10.4.
# $F[0] is the pid
# $F[1] is the username
# $F[2] is the first word of the command
ps -ww -A -opid,user,command | \
perl -nae 'if($F[2] =~ /\bloginwindow\b/) { system(
qq(launchctl bsexec $F[0] su $F[1] -c "launchctl load -w <your_plist>"))
}'
I have found no way to achieve this directly on 10.4. I cheat on 10.4 and just run the thing the LaunchAgent would have run, even though it has a GUI and you're not supposed to be able to do that (you can anyway in 10.4-10.6; you can't in 10.7). On 10.4, the LaunchAgent works correct after the next reboot.
The above code looks for loginwindow processes and uses bsexec to run commands in those contexts. Keep in mind that with Fast User Switching, there can be multiple contexts.
Some useful links:
Daemons and Services Programming Guide. You have to read it, but it won't actually answer any of the hard questions. But it will at least give you hints at where everything is located.
TN2083. This is a maddening document that raises as many questions as it answers, but is gospel and mandatory reading for anyone entering the abyss of launchd.
Starting/stopping a launchd agent for all users with GUI sessions. This has several other useful links and explanation.
IMO, launchd is one of the worst "great ideas" Apple has ever deployed. The idea is very useful, but the API is horrible.

Resources