piping 'ps' output via 'do shell script'

Dear MacScripter Mac OX List folks,

Thanks to all for the very useful info posted to this list. I’m usually able to answer my questions with a quick query to the archive.

This one has me stumped, and I couldn’t find anything in the archive.

I need to be able to use the Unix ‘ps’ command to grab the pid for a specific system process from within a large, compiled AppleScript I’m running.

The calls I started with on the Unix command line are:


[n2-129-789:~] dingus% ps xa -o pid,command | grep myProcess | grep -v grep | cut -d"/" -f1
  234
[n2-129-789:~] dingus%

This returns the number of the process named “myProcess” on the command line.

I can call this via ‘do shell script’, wrap it in a call to osascript and run it again on the command line with the same results:


[n2-129-789:~] dingus% osascript -e 'do shell script "ps xa -o pid,command | grep myProcess | grep -v grep | cut -d"/" -f1"'
  234 
[n2-129-789:~] dingus%

The only change I needed to make was to escape the quotes in the delimiter parameter passed to the Unix ‘cut’ command, put the collection of piped Unix statements in double quotes and put everything in single quotes before passing it as a parameter to the ‘osascript’ command.

Now I come to my problem.

I wanted to run this collection of piped commands from within a compiled AppleScript. Here’s the code:


set theProcName to "myProcess"
set theCmd to "ps xa -o pid,command | grep " &  theProcName & " | grep -v grep | cut -d"/" -f1"
set thePID to ((do shell script theCmd) as number)

Unfortunately, when I do this, no matter how I construct the command, the ‘ps’ command is always the last to be evaluated of my 4 Unix shell commands. Obviously, this completely screws up what I’m trying to do here, as the remaining 3 commands are just there to parse the output of the ‘ps’ command and grab the PID I’m looking for.

Normally, it’s no problem running a collect piped Unix shell commands in this manner and get them to run in the proper order. I’ve done it several times in scripts I use on a regular basis. This seems to be particular to the ‘ps’ command - or at least I’ve only discovered it to be the case so far for the ‘ps’ command.

I’ve tried several other ‘do shell script’ methods for achieving the same means - like running the same commands from within PERL or RUBY scripts. These all work from the command line and all give the same error from within my script.

Any help you can offer, I’d greatly appreciate.

Many thanks!

Cheers,
Bill Bug


Bill Bug
Senior Analyst
Computer Vision Lab for Vertebrate Brain Mapping
Rm. 282
Dept. Neurobiology & Anatomy
Drexel College of Medicine
2900 Queen Lane
Philadelphia, PA 19129
(215) 991 8430 (P)

Hi Bill. when I run your code…

set theProcName to "TextEdit"
set theCmd to "ps xa -o pid,command | grep " & theProcName & " | grep -v grep | cut -d"/" -f1"
set thePID to ((do shell script theCmd) as number)
--->result = 511

I replaced “myProcess” with “TextEdit” and it is returning the PID for TextEdit. I have a script that gets the PID from the process name. Maybe it has something in it that might help…

display dialog "Enter the Name of the Application You Wish to Kill" default answer ""
set appName to (text returned of result)
do shell script "ps ax | grep -i " & appName & " | grep -v grep | cut -c 1-6"
set pNum to result
set prName to do shell script "ps cax | grep -i " & appName & " | awk '{print $5, $6}'"
display dialog "Kill Application • " & prName & " PID#" & pNum buttons {"Kill It!", "Cancel"} default button 2
if button returned of result is "Kill It!" then
	try
		do shell script "kill -15 " & pNum
	on error
		display dialog "The Process Named "" & appName & "" Is Not Running"
	end try
end if

btw, I like your ‘cut’ method ;¬)

Hi Greg,

Thanks for getting back to me.

My code also was intended to pull the PID for the purpose of 'kill’ing a process from within a script. I have a large automation script that needs to shutdown a daemon - the Retrospect Client backup software - as it starts and then start it back up when it finishes.

It turns out when I try your code I have the same problem when trying to grab this particular process name ‘pitond’ - the name of the Retrospect Client process.

If - on the other hand - I use the name ‘Retrospect’ which appears in the process’s full path name then it returns the PID and I can kill the process.

It looks like it has something to do with the length of the string returned by the ps command. If I alter the parameters to include the ‘c’ option which drops the path and just gives the executable name, then everything works the way I want it to.


do shell script "ps cax | grep -i " & appName & " | grep -v grep | cut -c 1-6"

Thanks again for your help.

Cheers,
Bill

Would narrowing it down to…

ps -cax | awk '{print $1, $5}'

--sample output...
2460 QuickTime
2518 c++filt3
2519 Mail
2619 Safari
1794 X11
2646 login
2647 tcsh
2648 ps
2649 awk

help?

Exactly, that’s what the ‘c’ option does:


"ps xa -o pid,command | grep " &  theProcName & " | grep -v grep | cut -d"/" -f1"

The statement as given above works just fine and gives me the PID I need. I’m able to run the code the way I need to now.

The character string limit seems to be in the result given back by the ‘ps’ command.

The strangest thing - and what had thrown me off from the beginning - was the command without the ‘c’ option - the one that gives the entire process path back in the response works just fine when run via ‘osascript’ in the Terminal.

What’s that mean?

I assume ‘osascript’ is an interpreter, while an AS script is first compiled, then run. There must be a difference in the way these two tasks are carried out. The same AppleScript code snippet run either within ‘osascript’ or via an compiled AS script are not giving the same result.

This other part of the puzzle is we’re looking at a problem that’s happening when the script is being run. The ‘ps’ command result doesn’t exist until the AS code is run, so whatever is being done differently between ‘osascript’ and running the compiled AS script, it is happening at runtime.

Thanks again for help in working this out.

Cheers,
Bill

Bill, try doing a search for “osascript” in the Mac OS X forum, there are some pretty interesting tidbits that other folks have come across. In particular…

http://bbs.applescript.net/viewtopic.php?t=4375&highlight=osascript

My guess is something to do with the terminal widths and windows.

Do you have your terminal.app window set wider than the normal 40 characters?

When run in a terminal, ps shows as much of the executable’s path as can fit in the terminal width. If not running under terminal I’m assuming it defaults to 40 characters which might be truncating the process name.

The way to test this, of course, is to run the ps without the pipe to cut and see what you get.

-c fixes the problem because it eliminates the process’ path, just showing the executable.

-ww should also fix it since it forces ps to output the full path even if it exceeds the terminal width.