How can I halt a macro if a certain process is running?

Hello, everyone. I've got a script that wants to run every 5 minutes, looking for files to convert from WEBM to MP4 format using a process called handbrakecli. My Applescript tries to see if the process is already running, and quit if it is. This is the code that works when I manually test it, but not when running every 5 mins in KM.

--we need to make sure HandbrakeCLI doesn't exist
tell application "System Events" to set CurrentProcesses to name of every process

if CurrentProcesses contains "handbrakecli" then
	--say "not running handbrake cli, proceeding"
	--return 0
else
	say "running handbrake cli already, halting"
	return 1
end if

However this isn't working, and over time I end up with multiple instances of handbrakecli running, which really slows down my system.

My question is, how can I use KM to see if a certain process it running, then take an action (halt the macro) if it is, to give the first process time to finish?

A shell script command will get the answer much quicker, I think:

ps ax | grep HandBrakeCLI | grep -v grep

If the result of that command is empty (nothing), then HandBrakeCLI isn't running. If it returns any text at all, then it is running. So, in theory, just save the result of the script to a variable, and if that variable is not empty, then cancel your macro.

-rob.

Isn't your logic upside down? That script says to do nothing if Handbrake CLI is running and return 1 if it isn't.

Obviously it depends on how you then handle the returned 1 -- but having the script do the opposite of what its say will only cause confusion later!

But I do thnk that @griffman's solution will be generally faster/better. You probably don't even need the -a flag, since your screen shot suggests Handbrake CLI is running in your user space.

1 Like

Thanks, I will use this!

D'oh! I spent so long wondering why it wasn't doing what it was supposed to do. I will use his suggestion to streamline the script.

1 Like

I actually got this to work by removing the grep -v grep part, for some reason with that there it didn't return the results as expected. But it works great, thanks!

Odd; that should just have removed grep from the results. In any event, glad it's working!

-rob.

Actually it didn't work. Still trying to figure out why.

First of all, running

set theResult to do shell script "ps ax | grep HandBrakeCLI | grep -v grep"

yields a "The command exited with a non-zero status" error. So I used a try statement to get around this.

But before even running this script, I have a step that runs the ps ax | grep HandBrakeCLI | grep -v grep in a KM step and saves the result to a variable so I can pre-check it and avoid running the KM macro if handbrakeCLI is already running once. Long story short, it refuses to "see" the running process.

I'm definitely running an instance of handbrakeCLI, but the variable that holds the results of the terminal command is blank, which would cause the macro to run multiple instances, all likely trying to convert the same file.

Running "ps ax | grep HandBrakeCLI | grep -v grep" in terminal manually also yields no results even though HandBrakeCLI is visible in Activity Monitor.

Is there a different way to approach this?

(And interestingly, I ran another test of

set theResult to do shell script "ps ax | grep HandBrakeCLI | grep -v grep"

in Applescript just to see what the results were and it's hung for several minutes so far, perhaps because my system is so slowed down due to the handbrakeCLI process. I wonder if this is why the script cannot see that handbrakeCLI is already running, because of the slow system? But running ps ax | grep HandBrakeCLI | grep -v grep in Terminal also returns nothing so I'm confused.)

Damn it, it's definitely not seeing the process. With handbrakeCLI running in the background on a file conversion, running ps -u pp | grep HandBrakeCLI | grep -v grep in Terminal yields no results. So the machine overall is just not seeing that the process is already running.

Another possibility: is there a way to run a KM command at a certain time (every 5 minutes, say) but ensure that it won't try to run again until the first instance of the macro has ended completely? That would also solve my issue.

Take a look at the Semaphore actions:

https://wiki.keyboardmaestro.com/action/Semaphore_Lock

From the grep man page:

EXIT STATUS
     The grep utility exits with one of the following values:

     0     One or more lines were selected.
     1     No lines were selected.
     >1    An error occurred.

The command

ps ax | grep HandBrakeCLI | grep -v grep

...will return an exit code of either 0 -- the command succeeded because the HandBrakeCLI process was running -- or a 1 -- no lines were selected. If a shell script's final exit code is 1 then KM interprets that as the command failing -- which, to be fair, is usually correct. grep is an exception to the *nix rule.

You can try for yourself in the Terminal -- $? is the shell variable that holds the last exit code:

luggage:Steam nigel$ ps ax | grep MadeUpProcess | grep -v grep; echo $?
1
luggage:Steam nigel$ ps ax | grep MadeUpProcess; echo $?
  615 s002  S+     0:00.00 grep MadeUpProcess
0
luggage:Steam nigel$ 

You can mess around with the action's error options or maybe redirect the error to standard out in the script or something, but I think this is the easiest way round it:

ps ax | grep "MadeUpProcess" | grep -v grep || echo "Not found"

...which can be read as "return the process info for 'MadeUpProcess' if it is running, or (||) return 'Not found' if it isn't". I only chose "Not found" because that's a self-documenting known value you can then test your KM variable for.

As to why you aren't seeing HandBrakeCLI even when it is running? (One quick install later...)

Bad news is -- it works for me (macOS 10.14.6 test machine). I don't think it's a case-sensitivity issue, AFAIK Activity Monitor will use the same case as ps, but you could check by using -i on your grep.:

ps ax | grep -i handbrakecli | grep -v grep || echo "Not found"

This is all testing with HandBrakeCLI run from either a Terminal command or a manually-triggered KM macro -- I'm wondering if your launch method might be changing things somehow? Try manual launching and see if you have the same issues, and let us know your normal launch method so someone can try and replicate the problem.

Thanks for the info and help! Each process of handbrakeCLI is being launched from an Applescript that's theoretically running in KM every 3 minutes. The idea is that will check to see if a previous job is no longer running, then quit, until such time as there is no handbrakeCLI running. But it's not working.

Maybe I could do it with a variable. Set a variable to "busy" and then not re-run the operation until it's been set to "no longer busy."

Can you not refactor things to make use of KM's semaphores? Then you could use a "watched folder" trigger to process each file as it arrived -- another file dropping while one was being processed would have its instance paused until the previous completed, giving you a "first in first out" queue. Or if you are batch processing folder contents on a timer you'd use a semaphore with a 1/100th second time out so any instance that triggered while a previous one was running would immediately abort -- eventually the first instance completes and releases the lock and the next timed execution will be free to run.

I can't think of a reason why launching HandBrakeCLI would "mask" the process name in ps -- even running it via a LaunchDaemon under root would, I think, mean it was visible using the a flag. It might be worth grabbing a big list from Terminal next time HandBrakeCLI is doing its thing and going through it. Without knowing where you've installed it, the only thing we can safely omit are things run from the /System directory -- but just doing that should reduce the list by hundreds of processes :wink: The u will also let you know which user it is running as while ww maxes out the info on each process:

ps auxww | grep -v "/System/" > ~/Desktop/myProcessList.txt

You can then open ~/Desktop/myProcessList.txt in your favourite text editor and go hunting.