Need Help With "Do Shell Script" command and ssh

I have been pulling me hair out trying to get a script to run. (I know that is not good since I do not have much hair! :slight_smile: )

If I type “ssh -f -N rob@192.168.2.88” in a terminal, I can connect via SSH without any problems. I am not prompted for a passphrase since my private key does not have a passphrase associated with it.

If I run the following script, it runs without any problems:

try
	tell application "Terminal"
		do script "ssh -f -N rob@192.168.2.88 "
	end tell
on error
	display dialog "Error -- could not connect with Rob's computer.  Try again later" buttons {"OK"} default button {"OK"}
end try

But If I try this AppleScrpit, Applescipt freezes and I see the dreaded beachball:

try
		do shell script "ssh -f -N rob@192.168.2.88 "
on error
	display dialog "Error -- could not connect with Rob Kennedy's computer.  Try again later" buttons {"OK"} default button {"OK"}
end try

If I try “do shell script rob@127.168.2.88” the script runs and does not freeze but ssh is NOT started.

I would much prefer to use the “do shell script” command. Using “do script” opens up a terminal window.
In addition, using “do shell script” should allow me to display a message if the connection failed for some reason.

Does anyone know why “do shell script” is giving me so many problems?

Rob

AppleScript always uses /bin/sh. Is that your default shell in Terminal?

Yes, I am using bash or /bin/sh as my default shell in Tiger.

Rob

My TERMINAL preferences state:

“Execute the deafult login shell using /usr/bin/login”

I don’t seem to have any problems using the do shell command in Terminal tell blocks.

My problem is with the “do shell script” command that is supposed to execute any UNIX command that I can run in terminal. In my case, it does not. Am I missing something. Or is this a bug with the “do shell script” command?

Rob

Based on my testing, it appears that the hanging is caused by AppleScript waiting for the closure of the pipes it uses to capture output from do shell script commands. Since you are telling ssh to fork into the background, you will end up with an ssh process that still has its stdout and stderr connected to pipes into the AppleScript instance that launched the command. Since you are not actually executing a command on the remote side, you can probably just redirect the stdout and stderr of your command elsewhere and do shell script will continue once the initial ssh process has forked off its child (-f) and exited. If you do not care to look at the potential output from ssh (connection errors, authentication errors, etc.), then /dev/null should work nicely:

do shell script "ssh -f -N rob@192.168.2.88 > /dev/null 2>&1" -- Put it in a try block for the purposes of your original script

Ideally, you only want do this redirection for the forked process (so you could easily capture the output from connection or authentication errors, which come from the pre-fork process), but I do not know of an option in ssh for that. If you want this pre-fork output, you will have to redirect to a file and then read the data from the file back in AppleScript.

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 3.0.4 (523.12)
Operating System: Mac OS X (10.4)

Yes, do shell script can run anything that you can run manually in a Terminal window, but there are differences. Sometimes those differences are significant.

do shell script does not allow for stdin (it is always /dev/null). In Terminal stdin is the pseudo-terminal device used by the Terminal window.

stdout and stderr in do shell script are always pipes, but in Terminal they are the pseudo-terminal device (like stdin, the same device, in fact).

Your login shell is not used by do shell script. It always uses /bin/sh. Your login shell is likely bash, but it could be zsh, tcsh, ksh, or something else that has been added to your system (or, yes, even sh). These days /bin/sh is a copy of bash, but when it is run as sh still tries to act more like the POSIX-specified shell than normal bash, so it does not behave exactly the same as when it is started as bash.

The environment variables configured for programs run in do shell script are very basic. The one that most often causes problems for people is PATH. The login files that are normally sourced (run) by the login shell (as is normally used in Terminal) are not sourced for do shell script. This means that any changes to PATH (or any other environment variables) that you make in your .bashrc, .bash_profile, .bash_login, etc. are not necessarily represented in the environment that do shell script gives to the commands it runs. If you run the script via osascript in a Terminal window, do shell script will inherit its environment, but that ends up being a special case since most AppleScript is run through applets (scripts saved as applications), Script Editor, Script Debugger, the AppleScript menu, FastScripts, Quicksliver, etc. none of which will have used your shell configuration files.

See Technical Note TN2065: do shell script in AppleScript for some reference information.

Thanks chrys…

I have been playing around with your suggested script:

try
	
	do shell script "ssh -f -N rob@192.168.2.88 > /dev/null 2>&1"
	
on error
	display dialog "Error -- could not connect with Rob computer.  Try again later" buttons {"OK"} default button {"OK"}
end try

Your suggested script wotks fine when the remote computer is online. That is one great step forward. Thank you.
But if the remote host is not online, then the Applescript just hangs. I must open up a Terminal and type “killall ssh” to regain control of the script.

Do you know of anyway to prevent the script from hanging when the remote host is not online?

If not, I might have to go back to my approach using Terminal tell blocks and the “do script” command.

Rob

P.S. By the way, you might be curious why I am not sending a command via ssh. The ssh command that I will be using is as follows:

ssh -f -N -R 5900:127.0.0.1:5900 rob@192.168.2.88

In other words, I will be creating a reverse SSH tunnel…

The ssh process will eventually timeout while trying to connect, but the default time limit is the default TCP connection timeout, which is usually a least a minute (maybe 5 or 10). Luckily, the ssh program that comes with Mac OS X is fairly configurable. Try adding -o ConnectTimeout=5 to the parameters you give to ssh. That will reset the time limit to whatever you specify (5 seconds in the example). The number must be an integer, and 0 seems to mean “use the default value”.

I did wonder what the purpose was, but I guessed that you were doing some kind of port forwarding since the documentation for -N basically says it is there for port-forwarding-only situations.

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 3.0.4 (523.12)
Operating System: Mac OS X (10.4)

I’m having my own difficulties with ‘do shell script’

I have a Folder Action that moves files to a different folder, and then runs a script.

The script itself works. The Folder Action properly moves the files, but it doesn’t seem to ever run the script.


try
  do shell script "/usr/local/bin/sync_iweb >> /Users/me/rsync.log 2>&1"
end try

I tried putting the redirect into the shell script itself, which didn’t make a difference.

rsync.log never gets created. rsync is never run.

Help!

-brian

Brian,

This seems to be a mostly unrelated question. It might have been better to have started another thread.

I can not explain the problem. Even if /usr/local/bin/sync_iweb did not exist, I would still expect the shell to still have created your log file and captured an error message about the file not existing.

To diagnose the problem, I would start by adding an on error block to the try statement so that you can capture and report any error message. You might also make some sort of log/report before and after the try block so that you know the script actually got to the do shell script command (is there a return statement or the possibility of an error between the “move the files” code and the do shell script code?).

	display dialog "Right before "try"/"do shell script"" with title "Script Status" buttons {"OK"} default button 1
	try
		do shell script "/your/shell/command/here"
	on error the error_message number the error_number
		display dialog "Error: " & the error_number & ". " & the error_message with title ""do shell script" Error" buttons {"OK"} default button 1
	end try
	display dialog "Right after "try"/"do shell script"" with title "Script Status" buttons {"OK"} default button 1

Actually the script “not getting there” makes the most sense. Try adding diagnostic messages (like the before/after messages above) in various places in your script to see if execution gets to each of them. Also, I hear that Script Debugger has a way of debugging Folder Action scripts. That might make it easier to see if an error is coming up unexpectedly.

Model: iBook G4 933
AppleScript: 1.10.7
Browser: Safari 3.0.4 (523.12)
Operating System: Mac OS X (10.4)