I have an AppleScript that uses ffmpeg to process some files. Each single file process takes a while to complete. During this time I often need to run other AppleScripts that use the shell and ffmpeg but these scripts hang, waiting for the other script to complete the shell command.
Is there a way to open a separate instance of the shell per AppleScript so one does not interfere with the other and can run simultaneously?
I think using the do script command of the Terminal application it can be done. But as a person who also often has to code films, I can say that this makes little sense. The encoding speed is simply divided by the number of processes. Better, close all unneeded applications and processes to increase the speed.
tell application "Terminal"
do script "ffmpeg ...." -- one instance
do script "ffmpeg ...." -- second instance
end tell
Thanks @KniazidisR for the tip! No ideal to my use case since I collect data back from the shell command, I would have to figure out that part now using the terminal application.
So there is no way of doing these without opening Terminal?
BTW I’m not talking about processing more than one file to save time. Is more like SCRIPT#1 is running for hours at a time (takes about 30 minutes per file) and then I need to do a quick run of a different SCRIPT#2 that normally takes less than 10 seconds per file but I can’t, it hangs waiting for SCRIPT#1 to finish with its current file.
Create 2 scripts with one do shell script "ffmpeg …" in each, save them as 2 separate applications with unique names, and run them anytime, anywhere. Moreover, you will have complete control over them.
It is also possible (2 ways) to create instances of one single application located on the disk, but you will not have control over the instances (processes). So it won’t work for you.
The sdtout string could be a variable in bash script and then you could use pbcopy
to get the output to AppleScript.
I wonder why would you like to use AppleScript to start ffmpeg, would it not be a better approach
to make a log file in bash scripting for every job you do. At least that is what most people do I guess
when running tasks in shell environment.
AppleScript do not give you any extra in that regard, and you could open the log file anytime
with AppleScript or log editor like console.
set theScript to "#!/bin/bash
UsersHomeString=\"Users home:\"
UserHome=\"$UsersHomeString $HOME\"
UserString=
\"User name:\"
UserName=\"$UserString $USER\"
echo $UserHome $UserName | pbcopy
"
do shell script theScript
display dialog (the clipboard) as text
Or use bash loop to get data…
set theScript to "#!/bin/bash
UserHomeAndName=\"\"
for item in 'Users home:' $HOME 'User name:' $USER; do
UserHomeAndName+=\"${item} \"
done
echo \"$UserHomeAndName\" | pbcopy
"
do shell script theScript
display dialog (the clipboard) as text
Or if you like to have every command wth custom string per line you use quotation marks “”
ex.
set theScript to "#!/bin/bash
UserHomeAndName=\"\"
for item in \"Users home: $HOME\" \"User name: $USER\"; do
UserHomeAndName+=\"${item}\"
done
echo \"$UserHomeAndName\" | pbcopy
"
do shell script theScript
return (the clipboard) as text
So I created two very simple test script to try things out because I ended up waiting looong time to figure out the fix wasn’t working on my original scripts :lol: I hope I’m doing this test right, bear with me here:
S1:
set dResult to do shell script "sleep 5"
S2:
set dResult to do shell script "echo test"
display dialog "DONE!"
When I run (via AppleScript app) S1 and then S2 right after. S2 hangs for 5 seconds and then displays “DONE!” as expected (the issue in question)
However, if I save both S1 and S2 as independent apps, and run them from Finder, S1 then S2, the “DONE!” dialog is displayed immediately, before S1 finishes. So yeah @KniazidisR is absolutely right and this is an even better alternative to calling the terminal app. Thanks!
However, I would really like to figure out a way of doing this from AppleScript since I rarely save my scripts as apps (I’m always tweaking the scripts, calling scripts within scripts, calling scripts from other apps like LaunchControl, etc. I would have to change my workflow a bit :))
@Fredrik71, I’m trying to understand your approach. I’m not an expert in bash scripting and using variables in it but I think I understand your code and don’t see how it can help the issue in question. I changed S1 to the following:
S1:
set dResult to do shell script "#!/bin/bash
sleep 5"
You say you like to use AppleScript to start shell command, and before that is finish you
like to start a second one. You also say you like to return data from first or second back to AppleScript.
You need to execute the command in separate instance.
ex.
type this in terminal: osascript -e ‘delay 5’ -e ‘display dialog “5 seconds…”’ &
it will take 5 seconds and display dialog will come with a message. The character & means in unix
that it will run the command in background. If you later want to return data to AppleScript
you could use pbcopy or you could make a log file that AppleScript will read.
You couldn’t run the way you want directly in a Script Editor.
Yes, I would like to get data back from the shell command but I’m trying to solve the multiple shell instances issue first since you already gave me two great options for getting data back via pbcopy and log, and I might not even have to use them if I get the main issue resolved.
As I explained before, by saving the scripts as individual APPs and running them from Finder, both apps get their separate shell instance, allowing for concurrent operations. However, running the same scripts simultaneously from AppleScript (from their separate AppleScript windows) will cause one to wait for the other. It is as though only one shell instance is assigned to AppleScript.
Is there a way to invoke a separate instance from within AppleScript without having to use the terminal app?
I don’t see a technical reason as to why this shouldn’t be possible.
Sorry if you find inconsistencies in my posts, English is not my first language
Also do shell script could only return the last line from shell command.
If you like to return 2 lines or paragraph of the result from shell command its not possible.
To make AppleScript to script Terminal to use do script could return the contents of stdout. Meaning you later need to do text manipulation to find the string of data you want.
I would approach it this way.
First I would make bash script to use ffmpeg and make sure it only return what I like to have back when its finish. If its > 1 line of logging, I would save it to separate log file.
The log file could be in a separate folder and there I have folder action. Any change in that folder
would execute AppleScript with the information I want.
I have done this before but instead of using folder action I use notification center.
You have to save at least 1st script (S1) as app to solve your issue inside single script. Because AppleScript runs instructions one by one. It can’t run multiple threads the same time other way than using ignoring application responses block:
for example:
ignoring application responses
tell application "Delay5secondsApp" to activate -- use here 1st ffmpeg as app
end ignoring
tell me to display dialog "DONE!" -- use here 2nd ffmpeg as script: do shell script "ffmpeg..."