Applescript Sudo Solutions
by Dick Guertin
I've written this document to describe some other techniques for dealing with "sudo" commands and waiting for processes. These are alternative methods to those described in Applescript/Terminal.app Solutions.
Sorry for the mess. Many of my pages were mangled when I converted CLASSIC Site pages into NEW Site pages. My <pre> to </pre> constructs were stripped, and indented paragraphs were used instead.
First, to deal with "sudo" from within Applescript, it is possible to get all the information needed without getting a prompt for Password. The trick here is to supply the Password through a file, yet still hide the password. See Admin.Scripts for more examples. Consider the following commands executed in Terminal.app:
- $ cat - >key.inp
- mypassword
- $ uuencode -o encoded.psw key.inp myname
- $ chmod 600 encoded.psw
- $ cat encoded.psw
- begin 644 myname
- +;7EP87-S=V]R9`H`
- `
- end
Of course you'd substitute your password for "mypassword", and the result in the "encoded.psw" file would be your encoded password. You "chmod" so the file can only be read by your account. You can have anything for "myname", including "myname" or your short name.
Now that the encoded.psw file is established, here is a complete Applescript using it:
- global myKey, myVol, myUser
- set myVol to ""
- set myKey to " "
- ------------------
- try
- set myVol to ¬
- (do shell script "ls -d /Volumes/* | grep Mini40")
- end try
- if (myVol is "") then
- display dialog ¬
- "Mini40 disk missing" with title ¬
- "Mini40 disk missing" with icon stop ¬
- default button 1
- if button returned of result is "Cancel" then
- return
- end if
- end if
- ------------------
- set myUser to (do shell script "echo $USER")
- set myVerify to (do shell script "sudo -u " & myUser & " cd")
- if (myVerify is "") then
- set myCmd to "/Users/" & myUser & "encoded.exe"
- set myKey to (do shell script myCmd)
- if (myKey is greater than " ") then
- do shell script "/Library/StartupItems/Executor/Executor start &> /dev/null &" ¬
- user name myUser password myKey with administrator privileges
- delay 5
- Update()
- do shell script "/Library/StartupItems/Executor/Executor stop &> /dev/null &" ¬
- user name myUser password myKey with administrator privileges
- end if
- end if
- return
- ------------------
- on Update()
- tell application "Finder"
- launch application "DataBackup"
- delay 3 --give application a chance to start
- repeat until (exists process "DataBackup")
- delay 1 --wait for DataBackup to be ready
- end repeat
- repeat while (exists process "DataBackup")
- delay 10 --wait for DataBackup to finish
- end repeat
- end tell
- end Update
- ----------------
- This Applescript is saved as a Run Only application on my Desktop, where I can get at it quickly.
- This script is designed to run a disk backup application called DataBackup. My disk (Mini40) must be mounted, and a background task, called Executor (used by DataBackup), must be up and running. The first portion of this script insures that my backup disk is mounted. If not, the script terminates with a return statement if I "cancel".
- The second portion of this script establishes the password for "myUser", which is detected by the script. A "sudo" command is done in a special way to verify the myUser has administrator privileges. That command returns a null response if the user specified is running the AppleScript. "myUser" must be that user. Then, "myKey" gets the password by executing this "encoded.exe" Unix-script (shell script saved in your home directory):
- #!/bin/bash
- if [ -f "/Users/yourname/encoded.psw" ] ; then
- uudecode -o /tmp/encoded.key < /Users/yourname/encoded.psw
- cat /tmp/encoded.key
- rm -f /tmp/encoded.key
- else
- echo " "
- fi
- You would replace "yourname" in this script with your short name. What "cat /tmp/encoded.key" does is return the decoded value of your password back to the Applescript, where it gets stored in myKey. Note that if this decode can't be done, a blank (non-null) response is retuned so the AppleScript knows if the password was decoded.
- If you would prefer to enter your password directly using AppleScript, you could substitute a dialog for the encoded.exe, and encoded.key wouldn't be needed either.
- For example, you could replace:
- set myKey to (do shell script myCmd)
- with the following:
- try
- set myMsg to "Authenticate for " & myUser
- display dialog myMsg default answer "" with hidden answer
- set myKey to the text returned of the result
- end try
- We now get to the meat of the problem, running Unix-scripts and applications that require "sudo", but without using "sudo". This sample does three things:
- 1) It starts a background task called "Executor", which must be done by "root".
- 2) It runs the DataBackup application, and waits for it to finish.
- 3) It stops the background "Executor" task, again as "root".
- Any "delay" statements you see are there to give the tasks and applications time to start or stop before going on with the Applescript. The Update process launches DataBackup, waits for it to become active, and then waits for it to quit, which is done manually by the user when they're done doing the backup. Executor is only needed by DataBackup, so it is like a wrapper around DataBackup. Keeping Executor running all the time prevents your hard disk from going to sleep, even if you have "Put the hard disk to sleep whenever possible" checked in System Preferences -> Energy Saver. I have a shorter version of the AppleScript, saved as an application in my Home directory, that I execute from my Login Items under my Account. It is simply this:
- global myKey, myVerify, myExist, myUser
- set myKey to " "
- set myExists to ""
- set myVerify to ""
- ------------------
- set myLimit to 10 --give Executor a chance to start
- repeat while (myLimit > 0 and myExists is "")
- delay 5
- try
- set myExists to (do shell script "ps -wwax | grep '[E]xecutor.app'")
- end try
- set myLimit to myLimit - 1
- end repeat
- if (myExists is not "") then
- set myUser to (do shell script "echo $USER")
- myVerify to (do shell script "sudo -u " & myUser & " cd")
- if (myVerify is "") then
- set myCmd to "/Users/" & myUser & "/encoded.exe"
- set myKey to (do shell script myCmd)
- if (myKey is greater than " ") then
- delay 5
- do shell script "/Library/StartupItems/Executor/Executor stop &> /dev/null &" ¬
- user name myUser password myKey with administrator privileges
- end if
- end if
- else
- do shell script "logger -t 'Executor Stop' 'Executor not running' &"
- end if
- return
- This Applescript application stops Executor immediately upon system startup. Feel free to name it as you see fit. Remember, because you don't want a dialog at startup, it needs your encoded.exe and encoded.psw too. One last thing... if you try to copy and paste either of the Applescripts shown above, be careful with the Applescript continuation characters the the end of long lines. They are created using "Option-return" within Applescript, and they look like: ¬.
- Finally, a STRONG word of caution. Playing around with "sudo" can be dangerous. The wrong commands done by "root" can wipe you out. Know what you are doing. Test commands with the Script Editor by running harmless samples with Event Log turned on. Once you are as certain as you can be, try the real code. I always take a full clone backup of my system before I start playing around with "sudo" logic, just in case a disaster happens.
Dick Guertin's Google Home Page