Remotely rebooting multiple Macs at once - macos

We have a network of 9 Macs which I'd like to shut down all at once.
Right now I'm using this AppleScript but as you can see, it uses SSH to shut down the computers one by one. And if one of them is already down, the script will freeze.
Is there any way for me to shut all those Macs at once?
set finalIP to 100
repeat until finalIP is 109
tell application "Terminal"
activate
set success to 0
do script "echo Rebooting.."
do script "ssh -l username 192.168.1." & finalIP in front window
delay 1
repeat until success = 1
if last word of (contents of front window as text) = "no" then
do script "yes" in front window
delay 1
else if last word of (contents of front window as text) = "password" then
do script "password" in front window
set success to 1
do script "echo About to reboot.." in front window
else
delay 1
end if
end repeat
do script "sudo reboot" in front window
repeat until last word of (contents of front window as text) = "password"
delay 1
end repeat
do script "password" in front window
close front window
end tell
set finalIP to finalIP + 1
delay 1
end repeat
tell application "Terminal" to quit

You could simply set a timeout to the ssh connect:
ssh -o ConnectTimeout=10 -l ...
(This is a 10 second timeout, adjust to fit your need.)
Also really think about using keys for your connections. There is really no good reason to put SSH passwords in a script. (And if you do that, add the -o BatchMode=yes option too - it will skip hosts you can't log into with your key.)

The -o flag lets you specify a time out, so that when it doesn't succeed in connecting after the specified amount of seconds, it aborts.
imac$ ssh -o ConnectTimeout=5 123.45.6.7
ssh: connect to host 123.45.6.7 port 22: Operation timed out

Related

Terminal exit without performing action

I've made a script which have a block of code launching Terminal to retrieve picture from a server, using FTP.
When I run the script under the script editor, everything is OK: the script launch the Terminal, open the FTP session, set the destination path, get the files, delete them from the server, close connexion, wait the end of Terminal activty and then quit.
But when I run my Script as application, in about 90% of cases, the app launch Terminal and then Terminal quit immediatly. When the Terminal seems to "get" correctly the FTP commands, connexion is done, getting file and so on. Perfectly. But this happens only in a few cases.
Here the last code I have for this part:
tell application "Terminal"
activate
-- Wait for "no more activity"
set frontWindow to window 1
repeat until busy of frontWindow is false
delay 1
end repeat
-- Perform FTP actins
set shell to do script "ftp -i ftp://user_ftp:pass_ftp#host_ftp/" in window 1
do script "lcd ~/Desktop/tmp_instagram/" in shell
do script "mget *.jpg" in shell
do script "mdel *.jpg" in shell
do script "bye" in shell
-- Wait for no more activity
set frontWindow to window 1
repeat until busy of frontWindow is false
delay 1
end repeat
end tell
tell application "Terminal" to quit saving no -- Saving no to avoid conf alert
For avoiding you to loose your time, here are some of the tests I've made, without any success:
Setting the whole FTP command in one line so.
Put a delay 5 after the ativate, rather than the repeat on busy
Put a delay after the ftp command
In fact, the Terminal seems to close before receiving the FTP command (opened and closed immediatly).
Thanks to Mark Setchell comment I tried without using the "shell" command and in fact it seems to be the key. Here is a piece of code which run correctly:
tell application "Terminal"
activate
set w to window frontmost
do script "ftp -i ftp://xxxxx:yy#dddddd/" in w
do script "lcd ~/Desktop/tmp_aarecno_instagram/" in w
do script "mget *.jpg" in w
do script "mdel *.jpg" in w
do script "bye" in w
set frontWindow to window 1
repeat until busy of frontWindow is false
delay 1
end repeat
end tell

Access built-in Power Manager? states

Im trying to write a super simple applescript that will launch the OneDrive App, or ensure it is open, whenever the machine's power source is set to plugged in, and will quit, or make sure is closed, when the power source is set to battery.
I'm having trouble finding how to access the built-in "power indicator" in Yosemite. All of my searches lead to old, irrelevant results from years ago.
Edit: I think I will have to use a do shell script within the applescript using pmset -g batt
Now drawing from 'AC Power'
-InternalBattery-0 100%; charged; 0:00 remaining
And parse this result, but I am not sure how.
Edit: Here it is for anyone in the future who may want something similar:
global appName
on appIsRunning()
tell application "System Events" to (name of processes) contains appName
end appIsRunning
on acIsConnected()
return (do shell script "system_profiler SPPowerDataType | grep -q 'Connected: Yes' && echo \"true\" || echo \"false\"") as boolean
end acIsConnected
on toggleApp()
if my acIsConnected() then
if not my appIsRunning() then
tell application "Finder"
open application file (appName & ".app") of folder "Applications" of startup disk
end tell
end if
else
tell application appName
quit
end tell
end if
end toggleApp
-- This will only be executed once.
on run
set appName to "OneDrive"
end run
-- This will be executed periodically, specified in seconds, every return.
on idle
my toggleApp()
-- Execute every 2 minutes.
return 120
end idle
-- Not mandatory, but useful for cleaning up before quiting.
on quit
-- End handler with the following line.
continue quit
end quit
Here is a one-liner that polls for connected status, since I guess you can have less than 100% and still be connected (charging).
set acConnected to (do shell script "system_profiler SPPowerDataType |grep -q 'Connected: Yes' && echo \"true\" || echo \"false\"") as boolean
Here's another one liner...
set acConnected to last word of paragraph 1 of (do shell script "ioreg -w0 -l | grep ExternalChargeCapable")
If you are happy to use a third party tool, you can avoid polling for the battery state. This will make your script more efficient.
Power Manager can run AppleScripts when the battery state changes. How to Run a Command When Switching to Battery Power, walks through how to set this up for scripts.
Swap out the #!/bin/sh for #!/usr/bin/osascript in the script, and you can use AppleScript.
Disclaimer: I wrote Power Manager and can answer comments about how it works.
Provided you have battery icon on screen's top right:
tell application "System Events" to tell process "SystemUIServer" ¬
to value of attribute "AXDescription" of ¬
(first menu bar item whose value of attribute "AXDescription" ¬
begins with "Battery") of menu bar 1
You get "Battery: Charged" or "Battery: Calculating Time Remaining… " or something else

Apple script if while issiue

Hey guys my Applescript doesn't do what I expect.
Where is my mistake?
try
set NAS to do shell script "ping -c 1 192.168.222.5"
if NAS contains "100.0% packet loss" then repeat until NAS contains "0% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5"
end repeat
delay 20
tell application "Terminal" to activate
end try
I want ping to my NAS and when I don't get response I want to wake him up, but my script stops after send ping without response.
Any idea what I am doing wrong?
I want to send packets until the NAS wakes up.
I have changed the Code
try
do shell script "ping -c 1 192.168.222.5"
on error
set NAS to "100% packet loss"
repeat while NAS contains "100% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5"
if NAS contains "0% packet loss" then exit repeat
end repeat
say "Server startet, 20 sek"
delay 20
end try
tell application "Terminal" to activate
now i don't know how i get the loop to work with the on error command wich i get from the ping
Even if you have found the solution yourself there is no answer here so I try to complete it here. The string when we lay both strings on top of eachother we'll see "100.0%packet loss". As you can see when looking for "0% packet loss" it always will return true when you're sending just 1 packet. To be better safe than sorry you'd better match the entire line "1 packets transmitted, 1 packets received, 0.0% packet loss". Your first solution would be solved by changing the matches (also you can get rid if the if statement, if ping succeeds the first time the repeat will not run once):
set NAS to do shell script "ping -c 1 192.168.222.5 || true"
repeat until NAS contains "1 packets transmitted, 1 packets received, 0.0% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5 || true"
end repeat
delay 20
tell application "Terminal" to activate
Update: A better version who does not match the printed string from ping but matches the returned number and coerce it into a boolean value.
repeat until ping("192.168.222.5")
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
end repeat
delay 20
tell application "Terminal" to activate
on ping(IPNumber)
return (do shell script "ping -t 1 -c 1 " & IPNumber & " >/dev/null && echo yes || echo no") as boolean
end ping
the working script now:
try
do shell script "ping -c 1 192.168.222.5"
on error
set NAS to "q"
repeat until NAS contains "1 packets transmitted, 1 packets received, 0.0% packet loss"
do shell script "python /Users/Selim/Documents/scripte/wol2.0.sh"
delay 0.1
try
set NAS to do shell script "ping -c 1 192.168.222.5"
end try
end repeat
delay 5
end try
tell application "Kodi" to activate

Script to shutdown mac

I'm trying to automate the shutdown of my mac, I've tried the scheduled shutdown in energy saver and I wanna sleep but these don;t seem to work. VLC player runnign seems to prevent the shutdown. I think I need a script to forcefully shutdown the mac regardless of of what errors may thrown to screen by various programs running.
Thanks
Ok,
This is the applescript code im using to shutdown may mac. I've added it as an iCal event thats runs nightly.
tell application "System Events" to set the visible of every process to true
set white_list to {"Finder"}
try
tell application "Finder"
set process_list to the name of every process whose visible is true
end tell
repeat with i from 1 to (number of items in process_list)
set this_process to item i of the process_list
if this_process is not in white_list then
do shell script "killall \"" & this_process & "\""
end if
end repeat
on error
tell the current application to display dialog "An error has occurred!" & return & "This script will now quit" buttons {"Quit"} default button 1 with icon 0
end try
tell application "System Events"
shut down
end tell
Could you try a simple applescript, which goes something like this...
tell application "System Events"
shut down
end tell
See if it works, and then you can make it run through Automator at certain time, etc.
my solution (somwhat late). Just a bash script with apple in it:
#!/bin/bash
# OK, just shutdown all ... applications after n minutes
sudo shutdown -h +2 &
# Try normal shutdown in the meantime
osascript -e 'tell application "System Events" to shut down'
I also edited the /etc/sudoers (and /private/etc/sudoers) file(s) and added the line:
ALL=NOPASSWD: /sbin/shutdown
Always worked for me for an assured shutdown (knock knock ;-) )
This should do:
do shell script "shutdown" with administrator privileges
If you want to pass the admin password from key chain, with no prompt:
do shell script "shutdown" with administrator privileges password "password here"
But do not store the admin password in clear anywhere. Instead use the keychain access.
Alternatively you could kill all user processes, via:
do shell script "kill -9 -1"
This however would also kill your own Applescript process, preventing it from requesting the shutdown/restart afterwards.
Either way you're playing with fire, when using sudo or kill.
do what linux users do. use a bash script. if u dont know how to create one just go ahead and download ANY bash script u find using your internet search and open it with text edit app and paste the following:
( be careful if many people use the pc , then this method is not recommended, cause they can learn your user login password from inside this script )
#!/bin/bash
echo -n "Enter a number > "
read x
echo [your password] | sudo -S shutdown -h +$x
it will work the same way it works in linux. the terminal will pop up a message and ask you to enter a number. if we choose for exaple 50 , then the pc ( niresh ) or mac will shutdown in 50 minutes.

Sending commands and strings to Terminal.app with Applescript

I want to do something like this:
tell application "Terminal"
activate
do script "ssh user#server.com"
-- // write user's password
-- // write some linux commands to remote server
end tell
For example to log in to the server, enter the password, and then login to mysql and select a DB.
I type that every day and it would be really helpful to bundle it into a script.
Also, is there a reference of what commands, properties, functions, etc. do applications (Terminal, Finder, etc) have available to use within Applescript? thanks!
EDIT: Let me clear this up:
I don't want to do several 'do script' as I tried and doesn't work.
I want to open a Terminal window, and then emulate a human typing in some characters and hitting enter. Could be passwords, could be commands, whatever, just sending chars to the Terminal which happens to be running ssh. I tried keystroke and doesn't seem to work.
First connect to the server and wait for 6 seconds (you can change that) and then execute whatever you need on the remote server using the same tab
tell application "Terminal"
set currentTab to do script ("ssh user#server;")
delay 6
do script ("do something remote") in currentTab
end tell
As EvanK stated each do script line will open a new window however you can run two commands with the same do script by separating them with a semicolon. For example:
tell application "Terminal"
do script "date;time"
end tell
But the limit appears to be two commands.
However, you can append "in window 1" to the do script command (for every do script after the first one) to get the same effect and continue to run as many commands as you need to in the same window:
tell application "Terminal"
do script "date"
do script "time" in window 1
do script "who" in window 1
end tell
Note that I just used the who, date, and time command as an example...replace
with whatever commands you need.
Here's another way, but with the advantage that it launches Terminal, brings it to the front, and creates only one window.
I like this when I want to be neatly presented with the results of my script.
tell application "Terminal"
activate
set shell to do script "echo 1" in window 1
do script "echo 2" in shell
do script "echo 3" in shell
end tell
How about this? There's no need for key codes (at least in Lion, not sure about earlier), and a subroutine simplifies the main script.
The below script will ssh to localhost as user "me", enter password "myPassw0rd" after a 1 second delay, issue ls, delay 2 seconds, and then exit.
tell application "Terminal"
activate
my execCmd("ssh me#localhost", 1)
my execCmd("myPassw0rd", 0)
my execCmd("ls", 2)
my execCmd("exit", 0)
end tell
on execCmd(cmd, pause)
tell application "System Events"
tell application process "Terminal"
set frontmost to true
keystroke cmd
keystroke return
end tell
end tell
delay pause
end execCmd
You don't need to "tell" Terminal to do anything. AppleScript can do shell scripts directly.
set theDir to "~/Desktop/"
do shell script "touch " & theDir &"SomeFile.txt"
or whatever ...
Why don't use expect:
tell application "Terminal"
activate
set currentTab to do script ("expect -c 'spawn ssh user#IP; expect \"*?assword:*\"; send \"MySecretPass
\"; interact'")
end tell
Your question is specifically about how to get Applescript to do what
you want. But, for the particular example described, you might want
to look into 'expect' as a solution.
Kinda related, you might want to look at Shuttle (http://fitztrev.github.io/shuttle/), it's a SSH shortcut menu for OSX.
The last example get errors under 10.6.8 (Build 10K549) caused by the keyword "pause".
Replacing it by the word "wait" makes it work:
tell application "Terminal"
activate
my execCmd("ssh me#localhost", 1)
my execCmd("myPassw0rd", 0)
my execCmd("ls", 2)
my execCmd("exit", 0)
end tell
on execCmd(cmd, wait)
tell application "System Events"
tell application process "Terminal"
set frontmost to true
keystroke cmd
keystroke return
end tell
end tell
delay wait
end execCmd
I could be mistaken, but I think Applescript Terminal integration is a one-shot deal...That is, each do script call is like opening a different terminal window, so I don't think you can interact with it at all.
You could copy over the SSH public keys to prevent the password prompt, then execute all the commands joined together (warning: the following is totally untested):
tell application "Terminal"
activate
do script "ssh jdoe#example.com '/home/jdoe/dosomestuff.sh && /home/jdoe/dosomemorestuff.sh'"
end tell
Alternatively, you could wrap the ssh and subsequent commands in a shell script using Expect, and then call said shell script from your Applescript.
set up passwordless ssh (ssh-keygen, then add the key to ~/.ssh/authorized_keys on the server). Make an entry in ~/.ssh/config (on your desktop), so that when you run ssh mysqlserver, it goes to user#hostname... Or make a shell alias, like gotosql, that expands to ssh user#host -t 'mysql_client ...' to start the mysql client interactively on the server.
Then you probably do need someone else's answer to script the process after that, since I don't know how to set startup commands for mysql.
At least that keeps your ssh password out of the script!
Petruza,
Instead of using keystroke use key code.
The following example should work for you.
tell application "System Events"
tell application process "Terminal"
set frontmost to true
key code {2, 0, 17, 14}
keystroke return
end tell
end tell
The above example will send the characters {d a t e}
to Terminal and then keystroke return will enter and run
the command. Use the above example with whatever key codes you need
and you'll be able to do what you're trying to do.
what about something like this:
tell application "Terminal"
activate
do shell script "sudo dscl localhost -create /Local/Default/Hosts/cc.josmoe.com IPAddress 127.0.0.1"
do shell script "sudo dscl localhost -create /Local/Default/Hosts/cc.josmos2.com IPAddress 127.0.0.1"
end tell
As neat solution, try-
$ open -a /Applications/Utilities/Terminal.app *.py
or
$ open -b com.apple.terminal *.py
For the shell launched, you can go to Preferences > Shell > set it to exit if no error.
That's it.
I built this script. It is in Yosemite and it is bash script using AppleScript to choose a list of users for SSH servers. Basically you define an IP and then the user names.. when the application launches it asks who you want to login in as.. the SSH terminal is launched and logged in prompting a password...
(***
* --- --- --- --- ---
* JD Sports Fashion plc
* Apple Script
* Khaleel Mughal
* --- --- --- --- ---
* #SHELLSTAGINGSSHBASH
* --- --- --- --- ---
***)
set stagingIP to "192.162.999.999"
set faciaName to (choose from list {"admin", "marketing", "photography_cdn"})
if faciaName is false then
display dialog "No facia was selected." with icon stop buttons {"Exit"} default button {"Exit"}
else
set faciaName to (item 1 of faciaName)
tell application "Terminal"
activate
do script "ssh " & faciaName & "#" & stagingIP & ""
end tell
end if
I highly recommend though; Nathan Pickmans post above about Shuttle (http://fitztrev.github.io/shuttle/).. a very smart and simple application.

Resources