How to get pid of current script process

I have a script which is started with:

I need the script to know the pid of its own osascript process. That is because it needs to pass its own pid on to another process later. There can be a variable number of processes called osascript running at the same time so, I need a way to be specific.

I had thought of this:

tell application "System Events"
	set my_pid to unix id of my process
end tell
set result to this_pid

But, that failed with

Is there another way for a running process to get its own pid (when the name is ambiguous) ? Would using ps to find the most recent instance of osascript be a way ?

Thanks.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set theID to current application's NSRunningApplication's currentApplication()'s processIdentifier()

Shane, once again, you’ve solved my problem. Many thanks.

Garry

I spoke too soon. I get back “-1” instead of the process id. I put the ASOC into a try/on error block but, no error was triggered. Is the “-1” result an error ? If so, is there a way to get back the cause ? The process is named osascript. Is that a problem ?

Thanks.

From the documentation for processIdentifier:

In this case I’ve confirmed there is a pid. The pid relates to the osascript process not the script it runs. Perhaps that’s the issue.

I’ll find another way. Easiest (but cumbersome) would be to get the pid when calling the script, saving that in a temporary file and reading that file in the called script. That is:

set script_pid to do shell script "osascript" & script_file &  " & echo $!"

Then, save script_pid in a file and add code to script_file to read it. Another way would be for script_file to load the calling script and get the value of a global script_pid. Also, can still get the unique pid by looking for the most recent osascript process which in my case will always be the one needed.

I’ll do some testing.

Many thanks.

This will get you the pid of any app launched:

use framework "Foundation"
use framework "AppKit" -- for NSWorkspace
use scripting additions
on watchForAppLaunches()
	set theNSWorkspace to current application's NSWorkspace's sharedWorkspace()
	set theNSNotificationCenter to theNSWorkspace's notificationCenter()
	theNSNotificationCenter's addObserver:me selector:"appWasActivated:" |name|:(current application's NSWorkspaceDidActivateApplicationNotification) object:(missing value)
end watchForAppLaunches
on appWasActivated:theNSNotification
	set userInfo to theNSNotification's userInfo()
	set theApp to userInfo's valueForKey:(current application's NSWorkspaceApplicationKey)
	set theAppName to (theApp's localizedName()) as text
	set theID to theApp's processIdentifier() as integer
	display dialog (theAppName & " was launched with pid " & theID)
	stopWatchingForAppLaunches()
end appWasActivated:
on stopWatchingForAppLaunches()
	set theNSWorkspace to current application's NSWorkspace's sharedWorkspace()
	set theNSNotificationCenter to theNSWorkspace's notificationCenter()
	theNSNotificationCenter's removeObserver:me
end stopWatchingForAppLaunches
watchForAppLaunches()

Shane, many thanks again. I’ve afraid ASOC is beyond me at present. So, I’ve gone with just doing a pgrep -n osascript to get the most recent instance of my osascript calls. It’s a kludge but it works for my purpose.

Cheers.

Hello,

I wonder, whether the:

 set theID to current application's NSRunningApplication's currentApplication()'s processIdentifier()

could be modified to find the PID of a running process (it is a hardware driver that needs to be restarted) within a Sandbox environment, i.e. without using System Events unix syntax ?

Does anybody know? (maybe I should open a new post for this)

Thank you, Uwe

I created a multi threaded applescript program in which I also needed the PID of each osascript thread.
Here is what I did


set pid to do shell script "osascript '" & (POSIX path of (path to me)) as text) & "/TestClient.scpt' &>/dev/null & echo $!"


The last bit “& echo $!” will return the process ID when called

Thank you very much Robert. Yes that works with a script file, but I cannot get it do work with a driver.app? If you have any other idea, I would be grateful.

Is the driver.app written in AppleScript (i.e. a stay open application)?

also

is there only one osascript running?

if so then easy.


try
	set pid to (word 1 of (do shell script "ps -ecwwo pid,comm | grep osascript")) as integer
on error
	display alert "No osascript running!"
end try

Assuming you know the process’s bundle ID, you can use this:

use AppleScript version "2.5" -- macOS 10.11 or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

set bundleId to "com.apple.Safari" -- whatever
set thePid to ((current application's NSRunningApplication's runningApplicationsWithBundleIdentifier:bundleId)'s firstObject())'s processIdentifier()

Here is another way to get the Process ID by comparing the times the process started.


use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on run
	local cc, sc, i, pid, mdate, udate
	set mdate to (current date)
	copy mdate to udate
	set sc to paragraphs of (do shell script "ps -ecwwo pid,lstart,comm | grep osascript")
	repeat with i in sc
		set pid to (word 1 of i) as integer
		set cc to words 3 thru -2 of i
		set umonth to (offset of (item 1 of cc) in "XXJanFebMarAprMayJunJulAugSepOctNovDec") div 3
		tell udate to set {its month, its day, its year, its hours, its minutes, its seconds} to {umonth, item 2 of cc, item 6 of cc, item 3 of cc, item 4 of cc, item 5 of cc}
		if mdate = udate then exit repeat -- this is the correct pid
		set pid to 0 -- resets if date-times don't match
	end repeat
	-- pid now has the process id of this osacript
end run

if there is any delay from when the script first gets the date/time after it is launched
then change the last if statement to something like


if mdate - udate < 2 then exit repeat -- you can change the number from 2 to whatever your delay might be

Another way is to use passed arguments to find the correct osascript if more than one osascript is running.

The below code is your script run from a “do shell script” command

Call the script ThreadTest.scpt

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on run args
	local cc, osalist, i, pid, aid
	if class of args is list then -- arguments passed come in as a list
		set aid to item 1 of args -- 1st item is the random number passed as argument
	end if
	set osalist to paragraphs of (do shell script "ps -ecwwo pid,comm,args | grep osascript")
	set atid to text item delimiters -- save current text item delimiter
	set text item delimiters to " "
	repeat with i in osalist
		set pid to (word 1 of i) as integer
		if text item 3 of i is "osascript" then
			set cc to (text items 3 thru -1 of i) -- arguments passed to script
			if (item -1 of cc) is aid then exit repeat -- this one has the correct pid
		end if
		set pid to 0 -- resets if not osascript or correct script name
	end repeat
	set text item delimiters to atid -- resets text item delimiter back to what it was
	-- pid now has the process id of this osacript
	delay 25
end run

and here is the calling code that starts the osascript

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

local cpath, cid

set atid to text item delimiters
set text item delimiters to "/"
get (text items 1 thru -2 of POSIX path of (path to me))
set cpath to ((text items 1 thru -2 of POSIX path of (path to me)) & "ThreadTest.scpt") as text
set cid to random number from 11111 to 99999
do shell script "osascript '" & cpath & "' " & (cid as text) & " &>/dev/null & echo $!"
set text item delimiters to atid -- resets text item delimiter back to what it was

by passing the “cid” variable which contains a random number,
we are able to find ourself with the unix “ps” command and the arguments that were passed to it.

Thank you to all, I had to park that development for a week ago, as Catalina is creating challenges for one of my Applescript projects. But I will come back to it and then report, how it went.

Thank you already! Uwe

P.S. Now off to post another cry for help (In Catalina Xcode does not show me a Sandbox turn off/on capability and my code does not show the right behaviour colours - something got wrong upon transfer)

Although it seems like hitting a finishing nail with a sledge hammer, the following works:

do shell script “echo $PPID”

Note that this should work if the shell is zsh instead of bash as well.

Just to update that all versions work for me. I had to go to the respective app and via Show Package Content - Content - info.plist find out the right bundle identifier and then used Shane’s version ultimately.

Thanks again!

One other way to get pid of current process:


tell application "System Events" to tell process (current application's name) to unix id

Only if the process name is the same as the app name, which is not always the case.