I've searched around but couldn't quite find anything to fit my problem.
I want to create a script to replicate the following:
Open Terminal
Execute the following command:
sudo kextunload /System/Library/Extensions/AppleHDA.kext
Then have it enter my OSX admin password for me.
Then execute the following:
sudo kextload /System/Library/Extensions/AppleHDA.kext
I'm completely new to applescript, so hoping someone can help me out.
Thanks!
The hint in a comment on the question is correct (in [Apple]Script Editor, select File > Open Dictionary..., select StandardAdditions.osax, then search for do shell script to see the complete syntax), but it's important to note that do shell script will NOT open a Terminal window; instead, it'll run the shell command hidden and return its result - which is generally preferable:
do shell script's return value is the shell command's stdout output.
If the shell command returns a non-zero exit code, AppleScript will throw an error and the error message will contain the command's stderr output.
To run commands with administrative privileges, you have 2 options:
[Recommended] Let AppleScript display a password prompt:
set shCmds to "kextunload /System/Library/Extensions/AppleHDA.kext;
kextload /System/Library/Extensions/AppleHDA.kext"
# This will prompt for an admin password, then execute the commands
# as if they had been run with `sudo`.
do shell script shCmds with administrator privileges
[Not recommended for security reasons] Pass the password as an argument:
set shCmds to "kextunload /System/Library/Extensions/AppleHDA.kext;
kextload /System/Library/Extensions/AppleHDA.kext"
# Replace `{myPassword}` with your actual password.
# The commands will run as if they had been executed with `sudo`.
do shell script shCmds ¬
user name short user name of (system info) password "{myPassword}" ¬
with administrator privileges
As stated, if something goes wrong - whether it is because of an invalid password or a canceled password dialog or the shell commands returning a non-zero exit code - a runtime error is thrown.
Here's an example of trapping it and reporting it via display alert.
try
do shell script shCmds with administrator privileges
on error errMsg number errNo
display alert "Executing '" & shCmds & "' failed with error code " & ¬
errNo & " and the following message: " & errMsg
return
end try
Related
I would like to toggle between Enable/Disable in my applescript command. Can't seem to identify what's wrong with this script. It's not switching its states (toggling) when I run the same command again:
if {"disabled"} contains (do shell script "spctl --status") then
set theAllow to "enable"
else
set theAllow to "disable"
end if
do shell script (("sudo spctl --master-" & theAllow) as string) with administrator privileges
enter image description here
Looking at the source code for spctl, the spctl --status command will either return assessments enabled or assessments disabled. However, if it's disabled, then do shell script "spctl --status" exits with error "assessments disabled" number 1 and you'll need to account for it in some manner.
do shell script "spctl --status"
--> error "assessments disabled" number 1
So, to keep things simple, the following example AppleScript code simply toggles the state of spctl based on it status:
if (do shell script "spctl --status; exit 0") is "assessments disabled" then
do shell script "spctl --master-enable" with administrator privileges
else
do shell script "spctl --master-disable" with administrator privileges
end if
Example output when spctl is disabled while using ; exit 0 to handle error "assessments disabled" number 1:
do shell script "spctl --status; exit 0"
--> "assessments disabled"
do shell script "spctl --master-enable" with administrator privileges
As you can see, by using ; exit 0 after spctl --status, it stops error "assessments disabled" number 1 and allows the script to proceed.
There certainly is more then one way to trap the error, however, this example AppleScript code, that simply toggles the state of spctl, I've shown is simple and straight forward without the need to be more verbose with its error handling.
Otherwise you'll have to code it in a different manner, using a try statement wrapped around the do shell script "spctl --status command and an on error handler.
you could swap the 2 items
if (do shell script "spctl --status") contains "disabled"
assuming the returned string is "assessments disabled", and there's only 1 item to check.
Is there a way to write a "to do script" with administrator privileges like you can with a "do shell script" ? I have a script that I am writing that opens a terminal window and gets the size of another user account but I get permission denied errors. I can easily solve this by entering sudo before the command but I don't want to enter a password in the terminal window. I want to be prompted with a dialog so I can enter a password just like I would get if I used a "do shell script"
This is part of my script that I have:
tell application "Terminal"
activate
do script "sudo du -sh /Users/example"
end tell
I know that you can solve this also like this:
do shell script "du -sh /Users/example" with administrator privileges
but doing it like this opens a terminal window but does not start the command.
You can do it without involving Terminal.app at all
set userSize to do shell script "du -sh /Users/example | awk '{print $1}'" with administrator privileges
The awk command strips the size part from the result.
Your second option is correct, but it should not be used with a tell "Terminal" block at all.
With the script bellow (only the 2 lines), Terminal will not be open and the only window will be the one asking your admin password.
set UserSize to do shell script "du -sh /Users/test" with administrator privileges
display dialog UserSize
I am trying to let non-admin users run a script in a shared environment that requires root privileges. I was going to build either an AppleScript or Automator application that invokes expect in order to pass the login credentials (yes, I know the dangers, it will all be execute only). However I get the login to work, but the shell script I am trying to run doesn't seem to be executing, since it returns instantly. I am new to expect and I believe I have an error in my script. Ideas anyone?
#!/usr/bin/expect
set timeout 60
set password "MyPass"
set command "bash /Applications/mampstack-5.4.36-0/ctlscript.sh start"
eval spawn login admin
expect "assword:"
send "$password\n"
expect "$"
send "$command\n"
expect "$"
send exit
expect "$"
send exit
Don't do it that way. Instead, edit /etc/sudoers to add the following lines (or, on a default config of MacOS, you can create a file in /etc/sudoers.d with the following content):
# allow use by GUI apps (AppleScript, Automator), which don't have a TTY
Defaults:%staff !requiretty
# on MacOS, all humans are members of the staff group
%staff ALL=(ALL) NOPASSWD: /Applications/mampstack-5.4.36-0/ctlscript.sh start
...then, have your AppleScript or Automator code run:
sudo -u admin /Applications/mampstack-5.4.36-0/ctlscript.sh start
...which will require no password at all.
I have a command which takes 2 arguments.
When I run the command manually, I do this way:
cmd -i xyz.dat
hit enter
enter password in the prompt
hit enter
confirm password
My script needs to do the above operations without expecting user to enter password. I can hardcode the passwords in the file, but need a way to run this command successfully when I execute the shell script.
As on Feb 7th,
I have expect installed on my AIX. When I type expect at the command prompt, the prompt changes to expect 1.1> OS is 64 bit AIX
I have followed the instructions mentioned in the below comment, but I keep getting error - could not execute the command; no such file or directory"? I am able to manually run this command from same directory I am running the script. Besides that I have given the complete path of the command and the
file.
I am pasting another program I tried to su with root password as below: i get the same error message when I run the test program. I doubt if this is something related to quotes.
#!/bin/bash
set timeout 20
spawn "su"
expect "Password:" { send:"temp123\r" }
interact
Can someone please help me fix this error?
Sounds like you want to use expect. Here is a page with some examples.
So for your command you would want something like:
#!/usr/bin/expect
set timeout 20
spawn "cmd -i xyz.dat"
expect "<your password prompt" { send "<your password>\r" }
expect "<your password confirmation prompt" { send "<your password>\r" }
interact
I'm trying to write an automator service to fire up virtualhost.sh in a terminal.
Using the Services context menu the dialog opens to ask for the name of virtual host, then runs an applescript to launch terminal and pass in the input text.
What I want is to pass in my username and password to admin privileges so that I don't need to pass it in the terminal with sudo.
This can be done with do shell script but that executes a bin/sh and the virtualhost.sh is a bash script so I get the error bin/sh: virtualhost.sh command not found
Alternately I can use do script with command but this doesn't allow me to pass in the user name and password.
My code looks like so:
on run {input, parameters}
set vhost to "virtualhost.sh " & input
tell application "Terminal"
activate
do shell script vhost user name "user" password "pass" with
administrator privileges
end tell
end run
This produces the bin/sh error previously mentioned.
With do script with command
on run {input, parameters}
set vhost to "virtualhost.sh " & input
tell application "Terminal"
activate
do script with command vhost user name "user" password "pass" with
administrator privileges
end tell
end run
This produces an escaping error: Expected end of line, etc. but found property.
Is there a way to do this correctly?
Not specifically familiar with AppleScript Studio, but you can do it in plain old AppleScript (which appears to have the same issue) if you provide a full path to virtualhost.sh. (Also, Terminal is not required with "do shell script".) Example:
set vhost to "/usr/local/bin/virtualhost.sh " & input
do shell script vhost user name "user" password "pass" ¬
with administrator privileges
You can also extend $PATH (which is by default /usr/bin:/bin:/usr/sbin:/sbin with "do shell script") to include the path to virtualhost.sh, e.g.:
set vhost to "{ PATH=$PATH:/usr/local/bin; virtualhost.sh " & input & "; }"
do shell script vhost user name "user" password "pass" ¬
with administrator privileges
If you want a relative path, you can put virtualhost.sh inside the script application or bundle (e.g. in Contents/Resources), either in Terminal or by control-clicking and choosing "Show Package Contents". Then use "path to me":
set vhostPath to "'" & POSIX path of (path to me) & ¬
"/Contents/Resources/virtualhost.sh" & "'"
set vhost to vhostPath & space & input
do shell script vhost user name "user" password "pass" ¬
with administrator privileges
Per the comment on my other answer, I'm posting a secondary answer more in the spirit of that there's a will, there's a way, but it's a different, more dangerous approach. However, it's the only solution I can think of to this particular requirement (to get the interactivity of Terminal, but without having to prompt for an administrator password while running a script as administrator).
This solution runs Terminal as root, which is what do shell script "command" with administrator privileges does. This is dangerous because you have an open Terminal window with root access, so carefully weigh benefits against potential consequences of, say, opening a new Terminal window and being at the Bash prompt as root.
For this reason, the Terminal instance that is opened is killed upon completion of the script; if the "kill" command is removed, be aware you'll get multiple instances of Terminal, rather than multiple windows within the same instance.
No idea if this works in AppleScript Studio (it works in AppleScript Editor), but I can't think of any reason why it wouldn't.
set input to "some_input"
set vhost to "/usr/local/bin/virtualhost.sh " & input
set kill to ¬
"terminal_pid=$(</tmp/terminal_pid); rm /tmp/terminal_pid; kill $terminal_pid"
-- launch Terminal as root, and save its process ID in /tmp/terminal_pid
tell application "Finder" to set beforeProcesses to processes
do shell script ¬
"/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal " & ¬
"&> /dev/null & echo $! > /tmp/terminal_pid" user name "user" password ¬
"pass" with administrator privileges
-- wait until the new Terminal is confirmed to be running
tell application "Finder"
repeat while (processes is equal to beforeProcesses)
do shell script "sleep 0.5"
end repeat
end tell
-- Perform script in root Terminal window that we just opened,
-- and kill Terminal when done to prevent open root prompt
-- and multiple processes.
tell application "Terminal"
activate
do script vhost & "; " & kill
end tell
-- optional: wait until Terminal is gone before continuing
do shell script "while [[ ( -f /tmp/terminal_pid ) " & ¬
"&& ( \"$(ps -p $(</tmp/terminal_pid) -o%cpu='')\" ) ]]; do sleep 0.5; done"