2

I've been wanting to learn AppleScript, so I've been trying to create a simple script that will ssh into my dev server and input the password automatically when I call a function from the terminal (I'm aware that there are better ways to do this, this is merely an exercise).

This is my AppleScript:

tell application "Terminal"
    activate
    set SSH to "ssh [email protected]"
    if (count of windows) is 0 then
        do script SSH
    else
        do script SSH in window 1
    end if
end tell

delay 2

tell application "System Events"
    keystroke "somepassword"
    keystroke return
end tell

This works perfectly when clicking the Run button in the AppleScript editor, but when trying to call it from the terminal (osascript ~/Desktop/ssh_dev.scpt) it doesn't work.

The ssh [email protected] appears on the line, but does not execute and instead breaks to a new line meaning the "somepassword" string appears below it.

After the "somepassword" string is placed in the terminal, the ssh command executes and prompts me for the password.

Any help would be appreciated.

2
  • Don't do that. If you want to SSH into a server without entering the password yourself, set up public key login. Commented Jul 22, 2014 at 22:21
  • @duskwuff As I said in my initial description, I'm aware of that...Just trying to do this as an exercise. Commented Jul 23, 2014 at 16:29

2 Answers 2

3

What duskwuff said: do it using public key authentication if your use case is actually an ssh login.

More generally, however, the difference between your working scenario and your non-working scenario is not whether it’s run from AppleScript Editor or from the terminal. It’s whether it’s run from the same window as the ssh command or a different window. You can make that script work in the terminal just as it does from AppleScript Editor by removing the if/else/endif so that the terminal (which always has a window open, at least while typing a command in a window, and thus never has a count of 0) opens a new terminal window just like AppleScript Editor does:

tell application "Terminal"
    activate
    set SSH to "ssh [email protected]"
    do script SSH
end tell

(** etc. **)

The problem with “do script SSH in window 1” is that window 1 is the terminal that the script is running in. This means that the script has to complete in window 1 before window 1 can act on the commands it is given.

But by the time the script has completed, the password has already been keystroked in, and ssh doesn’t accept password data until it requests it. It’s likely you’ve seen similar things happen when manually logging in over slow connections. If you type the start of the password before ssh requests it, ssh ignores those characters.

I can think of one way around this problem if you’re willing to background the process. If you just add an ampersand to the end of the command, it goes into the background; this means that the terminal is now accepting input.

osascript ~/Desktop/ssh_dev.scpt&

This is a bit kludgy, because you can type into the terminal, too, and could easily type before the 2-second delay is up, preempting the text that is being keystroked in by the AppleScript. But it will work.

Similarly, if you’re not tied to using osascript and a text file, you could save the script as an application set to stay open, and then put the password injection into the idle handler. That’s getting pretty far afield of your requested conditions, however.

Another option might be to look into “expect” (use “man expect”). You should be able to construct an expect command line in AppleScript that will successfully provide the password to ssh, but that’s getting awfully complicated for this purpose.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Jerry. The issue I'm having with this solution is that when it's running from terminal, it opens a new Terminal window to run the command (which works), but I would like the command to run in the current Terminal window. Any ideas?
Unfortunately, you’re running into a basic limitation of procedural scripting here. The script has to pass control back to the terminal before the script sends the password. If this is just for your use, one option is to put the ampersand at the end of the command when running it on the command line. I'll add that to the answer.
0

If you already have Terminal as an "Active" window then:

Its the missing tell process, that may have been the problem

tell application "System Events" to tell process "Terminal"
    keystroke "somepassword" as text
    key code 36 -- return
end tell

That's is one method.

Also when you run the terminal script, you can start is by saying do script and then any scripts you want to run after should be do script "blah" in window 1 or in front window

Or another suggestion, although this is untested...

tell application "Terminal"
    activate
    do script "ssh [email protected]"
    do script "somepassword" in front window
end tell

That should just run the "somepassword" script as a if you typed that and hit enter... (I think)

In response to: "The issue I'm having with this solution is that when it's running from terminal, it opens a new Terminal window to run the command (which works), but I would like the command to run in the current Terminal window. Any ideas?"

try
    do script "" in front window
on error
    do script ""
end try

This will do the script in the front window if it exists. If not then it will open a new one.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.