Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

Pass arguments and run GUI AppleScripts via cron System
A few weeks ago, this hint detailed a way of grabbing arguments from an iCal event and using them to record radio streams. Up until then, I'd been using six essentially identical scripts fired off by iCal to record different streams, because there was no way of passing arguments to a single AppleScript. Being a neat freak, I wanted to use one script, and I hoped this was the solution.

Unfortunately the script fails because it doesn't work with recurring events. If only iCal could pass the unique event identifier to alarm scripts, it would solve everything. But it doesn't. So I looked at using crontab to run my script contained within a shell script. But I ran into a wall I've run into many times before: You can't run AppleScripts which require user interaction from cron unless you are logged in. My scripts also make use of UI Scripting, which won't work behind a screensaver. The only option is to be logged in and switched out and use iCal.

The above hint launched me along the path to finally discovering the solution: Folder Actions. A simple shell script could be passed arguments from cron and then drop them into a text file in a folder. A Folder Action would then act on that file and extract variables from it.

Here's the shell script:
#!/bin/sh
# take the first argument as the path to the folder 
# with the attached folder action
thePath="$1"

# remove existing arguments file if it exists. 
# The -f just supresses the error if the file does not exist
rm -f "${thePath}/folder-action-arguments.txt"

# this tiny delay is necessary because if the file 
# did exist before then Finder will not notice the new file
# arriving as it is replaced too quickly otherwise
sleep 4

# this bumps the first argument off the list (defined path)
shift 1
 
# the curly braces are used to supress output until the code 
# block is complete, then everything generated in the block is
# output to file at the end (after the closing brace)
{
    for i in "$@"
    do
        echo ${i}
    done

}>"${thePath}/folder-action-arguments.txt"
I've saved the script as osaargs in /usr/bin. It takes the first argument as the path to the folder with the attached action you want to perform:
osaargs "/Users/your_user/foldername" "argument one" banana "argument 3" fish
It will then create a new text file in the specified folder, which this AppleScript will pick up and extract the arguments from:
on adding folder items to actionFolder after receiving actionFile
    
    set thePath to quoted form of (POSIX path of actionFile)
    set scriptToDo to "cat " & thePath
    set argArray to (do shell script scriptToDo)
    set passedArgs to paragraphs of argArray
      
    set var1 to (item 1 of passedArgs)
    set var2 to (item 2 of passedArgs)
    set var3 to (item 3 of passedArgs)

(*
DO YOUR STUFF HERE USING THE var# VARIABLES
*)

    tell application "Finder"
        move file (actionFile) to the trash
    end tell
      
end adding folder items to
The script only moves the file to the trash; it doesn't empty it just in case you manually drop something into that folder at some stage. Since the folder action was launched independently of the cron, it bypasses the security restrictions placed on cron scripts and can perform UI interaction, too.

[robg adds: I haven't tested this one.]
    •    
  • Currently 2.00 / 5
  • 1
  • 2
  • 3
  • 4
  • 5
  (3 votes cast)
 
[11,920 views]  

Pass arguments and run GUI AppleScripts via cron | 7 comments | Create New Account
Click here to return to the 'Pass arguments and run GUI AppleScripts via cron' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
Pass arguments and run GUI AppleScripts via cron
Authored by: leenoble_uk on Sep 19, '05 10:48:13AM

That should read: the previous submitted script doesn't work for me because of limitations with recurring events, a fault which the author acknowledges and is iCal's fault.

What I've done is made a new folder at ~/Library/Scripts/Folder Action Scripts/Action Folders which houses a new empty folder for each script I want to run from the cron. I have then modified the shell script to hardcode that path so I only need to specify the empty folder name as the first argument. I've been advised it might have been a good idea to set that path as a shell variable to avoid typing it each time. In any case to record any radio stream now all I have to do is use this command


/usr/bin/osaargs Radivo Breakfast http://ms2.captialinteractive.co.uk/xfm_low

...or similar variant. Issuing STOP as the second argument stops the recording so now I have one script to start and stop which is a lot neater.

---
So, I said ... well, I can't actually remember exactly what I said. But it was one of the most enormously cruel and frighteningly witty put downs ever.

[ Reply to This | # ]

iDo that too
Authored by: ever on Sep 19, '05 12:26:55PM
While yours is a clever solution, I personally prefer to use this little app (shareware, $25) to pass parameters to my scheduled scripts.

[ Reply to This | # ]
iDo that too
Authored by: leenoble_uk on Sep 19, '05 01:32:03PM

I used to use iDo on OS9. I waited a couple of years I'm sure after upgrading to X for it to be converted but eventually gave up checking. Since rolling my own solution last Friday I've been pointed towards Script Timer too. I've read many postings on various sites and mailing lists asking why their scripts stop working when run from the cron and I've yet to see anyone offer a solution. I'll be sticking with my solution though. It is completely free after all.


---
So, I said ... well, I can't actually remember exactly what I said. But it was one of the most enormously cruel and frighteningly witty put downs ever.



[ Reply to This | # ]
Pass arguments and run GUI AppleScripts via cron
Authored by: pauljlucas on Sep 19, '05 12:51:10PM

Echoing the args can be simply:

echo $* >/some/file

---

- Paul



[ Reply to This | # ]
Pass arguments and run GUI AppleScripts via cron
Authored by: lar3ry on Sep 19, '05 01:50:08PM
First, notice that the original poster used "$@" (in quotes). That is subtly different than the simplistic $* that you suggest. The difference is that shell will correctly process complex arguments if necessary (eg, if one or more arguments passed has spaces in it as in the original poster's test example).

Second, the original script outputs a single line for each (quoted) argument.

Third, the applescript extracts the arguments by using set passedArgs to paragraphs of argArray. This means that each line in the file is a single item in passedArgs.

The original solution is therefore much more flexible and rubust and it's also less error prone than your "optimized" solution, which will fail at unexpected times.

Shell programming can be simple, but there are many subtle complexities, which aren't really for the faint of heart.

[ Reply to This | # ]

Pass arguments and run GUI AppleScripts via cron
Authored by: leenoble_uk on Sep 19, '05 02:47:20PM

I'm no Shell guru myself. It took quite a lot of repeated Google searches and misplacing of quotes to reach that end. I was trying to use backslash-n to generate new lines. I used odd sequences of characters as argument delimiters. Apparently you can contract it further by removing the curly braces and writing:


ARGFILE="${thePath}/folder-action-arguments.txt"

for i in "$@"; do
echo "$i"
done > "$ARGFILE"

Also since the 4 second sleep is only necessary if the file existed before then


if [ -f "$ARGFILE" ]; then
    rm "$ARGFILE"
    sleep 4
fi

will remove the delay. Credit to Mark J Reed on the Applescript Users mailing list for that.

By the way, the Applescript needs to be amended to move the file.
It should read:


move file (actionFile as string) to the trash

---
So, I said ... well, I can't actually remember exactly what I said. But it was one of the most enormously cruel and frighteningly witty put downs ever.

[ Reply to This | # ]

Pass arguments and run GUI AppleScripts via cron
Authored by: Yuckandmuck on Sep 20, '05 11:19:59AM
A followup to this hint turned me on to using UNIX environment variables to pass arguments to applescripts. Basically, I have a wrapper shell script that does little more than take the argument I passed in on the command line (or via cron), export it as a UNIX environment variable, and then call the applescript, which reads that environment variable.

Something like this:

myscript.sh:


#!/bin/sh
myarg="$1"
export myarg
osascript myscript.scpt

myscript.scpt:


set myarg to system attribute "myarg"
...

You can then use myarg throughout the applescript.

Not sure if this helps with the problem you're trying to solve, but thought I'd pass it along fwiw. It's been a useful method for me and apparently isn't tied to a particular release of OS X.

[ Reply to This | # ]