How do I use "on error" with "mount volume"?

I am trying to add a “mount volume” to a script I’m working on so I can then copy folders to it. In keeping with smart scripting, I am trying to catch any errors that may pop up; specifically in case the computer to be mounted is offline.

During testing, when I have the volume to be mounted off (in my case a G4), my script just hangs there and eventually crashes the Finder. Last week, I tried adding a “timeout” & “error number -1712” to solve the issue but it still hangs, though it no longer crashes the Finder. Any suggestions?

set IPServerAddress to "###.##.###.###"
set volumeName to "G4Server"
set theUserName to "user"
set thePassword to "password"
set mountG4 to mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
tell application "Finder"
	try
		with timeout of 15 seconds
			if not (exists disk "G4Server") then
				mountG4
			end if
		end timeout
	on error number -1712
		display dialog "The G4Server is not available for connection. 
To try again, please make sure the G4 is on and then click Retry.

If you would like to use your own computer to upload this art, click Mine. (NOTE: If you choose this option, the script will NOT send an email to the printer to notify them of the FTP upload.)

Click Cancel to quit." buttons {"Retry", "Mine", "Cancel"} default button {"Retry"}
		set mountButton to the result
		if mountButton is "Retry" then
			set repeatLoop to true
			repeat while repeatLoop is true
				try
					with timeout of 15 seconds
						mountG4
					end timeout
					if (exists disk "G4Server") then set repeatLoop to false
				on error number -1712
					display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
					set loopButton to the result
					if loopButton is "Cancel" then
						return
					end if
				end try
			end repeat
		else if mountButton is "Mine" then
			display dialog "The WorkStation script would now execute."
		else if mountButton is "Cancel" then
			return
		end if
		beep 3
	end try
end tell

Test first to see if the server is answering pings, perhaps, before proceeding with the rest:

word 7 of (do shell script "ping -c 5 xx.yy.ww.zz | grep transmitted") = "0"

True if the server responds, false if not. (the -c 5 is the number of pings)

EDIT: “0” is the number of packets lost as text. If this is flaky, you might try:

word 7 of (do shell script "ping -c 5 192.168.1.3 | grep transmitted") as number < 5

Adam,
Thanks for the reply. I think we’re on the right track although I’m not familiar with Shell Scripts at all.

This seems to work properly:

repeat while word 7 of (do shell script "ping -c 5 XXX.XX.XXX.XX | grep transmitted") is not "0"
	display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
	set loopButton to the result
	if loopButton is "Cancel" then
		return
	end if
end repeat
beep 3

Whenever the G4 is on/available, this beeps 3 times. Whenever it is not on/available, I get the dialog box and it loops properly.

But when I try to put your shell script into the larger context of my script it just hangs:

set IPServerAddress to "XXX.XX.XXX.XX"
set volumeName to "G4Server"
set theUserName to "user"
set thePassword to "password"
set mountG4 to mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
tell application "Finder"
	if word 7 of (do shell script "ping -c 5 XXX.XX.XXX.XX | grep transmitted") is "0" then
		mountG4
	else
		display dialog "The G4Server is not available for connection. 
To try again, please make sure the G4 is on and then click Retry.

If you would like to use your own computer to upload this art, click Mine. (NOTE: If you choose this option, the script will NOT send an email to the printer to notify them of the FTP upload.)

Click Cancel to quit." buttons {"Retry", "Mine", "Cancel"} default button {"Retry"}
		set mountButton to the result
		if mountButton is "Retry" then
			repeat while word 7 of (do shell script "ping -c 5 192.68.101.248 | grep transmitted") is not "0"
				display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
				set loopButton to the result
				if loopButton is "Cancel" then
					return
				end if
			end repeat
			mountG4
		else if mountButton is "Mine" then
			display dialog "The WorkStation script would now execute."
		else if mountButton is "Cancel" then
			return
		end if
		beep 3
	end if
end tell

Is this happening because I’m now talking to the Finder? Maybe I’m missing something? I don’t quite understand how I’d use the second option you gave me:

word 7 of (do shell script "ping -c 5 192.168.1.3 | grep transmitted") as number < 5

Any further suggestion are very welcome.

I can’t run your script (don’t have a server running) but I would enclose the “mountG4” statements in “try blocks”


-- test
try
mountG4
on error E
display dialog E
end try

to see if you’re ignoring an error message of some sort.

Missed your second part:

Replace: word 7 of (do shell script “ping -c 5 XXX.XX.XXX.XX | grep transmitted”) is not “0”

with: word 7 of (do shell script “ping -c 5 xxx.xx.xxx.xx | grep transmitted”) as number < 5

and, btw, you left one ip address in your script (not that it matters, it’s a private address inside your router)

Adam,
Thanks again for the reply. I understand what you are saying about putting the “mount server” inside a try block but I may not have explained what I meant when I said it is still “hanging”.

When the server is on/available the latest script with the addition of your shell script works to mount the server. The problem occurs when I’ve got the server off/unavailable on purpose; to see if it moves over to the “diplay dialog”. Under those circumstances is when the script hangs.

I fully intend to build in some other form of “try, on error, end try” type error checking but I thought this “ping-method” you have supplied me with should test to see if the server is online and subsequently able to be mounted. At this point, I would think that adding a try block will only make it harder to see what the real issue continues to be. (I could be wrong about that because I’m still a beginner at this.)

I’ll play with it some more to see what happens. Let me know if you have any other thoughts.

Concerning the alternate version you gave me:

word 7 of (do shell script "ping -c 5 192.168.1.3 | grep transmitted") as number < 5

I can see what is different than the ‘…= “0”’ version but I’d love to understand the difference. Would you mind explaining it to a newbie?

Sure thing. Run this on your machine with your server running

set p to (do shell script "ping -c 5 192.68.101.248")
p

You’ll get a response like this (the times will be different, in general):

What we’re interested in is the line telling us that there was no packet loss - the pings were sent and received. Occasionally, if a machine is busy, it will miss the first, so that line might read something other than 0%, but if it says 100%, the machine is down.

grep is a unix tool for finding the first line in a text containing a specified word, and “transmitted” only occurs once in this whole message, so I used it to find the line of results. My second version, I see now, is wrong, by the way. What I should have said was this:

word 4 of (do shell script "ping -c 5 192.68.101.248 | grep transmitted") as number > 3

The fourth word of the line containing “transmitted” is “5” in the text above. As number, that’s 5. If we get more than 3 packets back, we’re probably OK - the server is busy or the connection is lousy, but it’s there.

Sorry for the confusion - no wonder you couldn’t see what I was aiming for; I wasn’t aiming for it.

Anyway - use the corrected second version above and see if that helps.

Here it is, modified:

set IPServerAddress to "192.68.101.248"
set volumeName to "G4Server"
set theUserName to "user"
set thePassword to "password"
set mountG4 to mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
tell application "Finder"
	if word 4 of (do shell script "ping -c 5 192.68.101.248 | grep transmitted") as number > 3 then
		mountG4
	else
		display dialog "The G4Server is not available for connection. 
To try again, please make sure the G4 is on and then click Retry.

If you would like to use your own computer to upload this art, click Mine. (NOTE: If you choose this option, the script will NOT send an email to the printer to notify them of the FTP upload.)

Click Cancel to quit." buttons {"Retry", "Mine", "Cancel"} default button {"Retry"}
		set mountButton to the result
		if mountButton is "Retry" then
			repeat while word 7 of (do shell script "ping -c 5 192.68.101.248 | grep transmitted") as number > 3
				display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
				set loopButton to the result
				if loopButton is "Cancel" then
					return
				end if
			end repeat
			mountG4
		else if mountButton is "Mine" then
			display dialog "The WorkStation script would now execute."
		else if mountButton is "Cancel" then
			return
		end if
		beep 3
	end if
end tell

Wow, thanks for the details. I appreciate your help with this. Would you say that a good AppleScripter needs to learn how to use shell scripts? Seems like it would be helpful. Can you recommend any good resources; books, websites, etc.?

BACK TO THE SCRIPT…
Previsously, it appeared as though the Script Editor was hanging/crashing and I would force quit it every time but…
After waiting a considerable amount of time, the “Script Editor” does come back with an AppleScript Error, it reads:
“Disk G4Server wasn’t found.”
I even added in a check to see if this error is coming from the “ping” or the “mount volume” and it looks to be coming from the “ping” shell script.

QUESTION: When you ping a volume that is off/unavailable, will it always come back with an error? May assumption when you suggested this “ping” shell was that it would not. Where should I go from here? Should I add a “with timeout” to the ping?
(Another note that I failed to mention is that this “server” is not a traditional server but actually an old PowerMacG4 that has been sitting around doing nothing and I am tasking into a “slave” to do a lot of busy work so I won’t have to. Not sure if that matters but in the interests of full disclosure…)

I must confess that I picked them up in pieces. To see how things work, run the Terminal (in Utilities) and after the prompt, which ends in your username$, type ‘man ping’ without the single quotes and press the return key (not enter). To see more, press the space bar. To get help, press h. q gets you out (or just quit the Terminal).

On my machine, 15 seconds elapses before I get a response. One of the downsides of shell scripts is that once the command is issued, the AppleScript sits waiting for a response and you have no way to interrupt. Ping, however, has a timeout option set with -t (no space) followed by the number of seconds you’re willing to wait (10 in the example). The actual time will be slightly longer than that because the ping process has to get going and the message has to be sent back to the script.

set p to word 4 of (do shell script "ping -c 5 -t 10 192.168.1.102 | grep transmitted") as number > 3
p

After quite a few trials, I did get an error. Mostly it returned 0 packets received. Here’s how you handle errors:

set IPServerAddress to "192.68.101.248"
set volumeName to "G4Server"
set theUserName to "user"
set thePassword to "password"
set mountG4 to mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
try
	set p to word 4 of (do shell script "ping -c 5 -t 10 your.num.here.xxx | grep transmitted") as number > 3 -- true if the G4 answers, false if less than 3 packets are received.
on error -- this is insurance just in case ping returns an error, which it did to me once
	set p to false
end try

tell application "Finder"
	if p then
		mountG4
	else
		set mountButton to button returned of (display dialog "The G4Server is not available for connection.
To try again, please make sure the G4 is on and then click Retry.

If you would like to use your own computer to upload this art, click Mine. (NOTE: If you choose this option, the script will NOT send an email to the printer to notify them of the FTP upload.)

Click Cancel to quit." buttons {"Retry", "Mine", "Cancel"} default button {"Retry"})
		
		--- etc
		
		
	end if
end tell

hi simple, adam,

here are my favorite three books on shell scripting and Unix administration:

UNIX Power Tools
System Administration
The Purple Book

the first two have more shell scripting in them but all are good. they range from the basics to some in depth coverage. you’ve reminded me that i should probably reread these.

cheers.

I forgot to mention that for functions without timeouts or whenever you want to limit a wait for something:

with timeout of 12 seconds -- or whatever
-- do your thing
end timeout

Adam,
I hesitate to even write again because I don’t want to be a pain…

I’m still having problems. I’ve cut it down to the very basics; trying to narrow down the problem. Here are 2 versions of the same script; one works, one does not.

This one beeps when the G4Server is on/available and it goes into the repeat loop with the “display dialog” when the G4Server is off/unavailable. This is what I would like the “ping” shell script to do for me in the larger script.

repeat while word 4 of (do shell script "ping -c 5 XXX.XX.XXX.XXX | grep transmitted") as number < 3
	display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
	set loopButton to the result
	if loopButton is "Cancel" then
		return
	end if
end repeat
beep 3

…but when I add even some basic variables in front of the shell…
This one beeps when the G4Server is on/available but the “Script Editor” comes back with an AppleScript Error:
“Disk G4Server wasn’t found.” whenever the G4Server is off/unavailable. It never goes into the repeat loop like it should.

set IPServerAddress to "XXX.XX.XXX.XXX"
set volumeName to "G4Server"
set theUserName to "user"
set thePassword to "password"
set mountG4 to mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
repeat while word 4 of (do shell script "ping -c 5 XXX.XX.XXX.XXX | grep transmitted") as number < 3
	display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
	set loopButton to the result
	if loopButton is "Cancel" then
		return
	end if
end repeat
beep 3

What is going on here? Why would defining a few simple variables cause any issues here? (Notice, I haven’t even tried to mount the volume!) Is there some sort of scripting additions that I’m missing? Any advice is welcome. Thanks.

Jacques,
you are exactly right!

I thought that I could assign that “mount volume” to a variable but it actually tries to mount volume rather than acting as a variable. Once I removed the “set mountG4…” from the beginning of the script, it works.

Adam,
What Jacques pointed out seems to be the difference that is causing you to “After quite a few trials, I did get an error.” and me to get an error EVERY time.

As you can see below, I cut down the “Ping” timeout to 4 because that is the shortest time it seems to need for my current setup. Do you think that is a mistake? I don’t know too much about what is optimal for the many conditions that could occur but I’d like to cut down that time to as short as possible. Please advise.

Another thing that I’d like to understand better is the line that you suggested “if p then”. When I put that line in my script, I used “if p is true then”. Is your way just a shorter way? Does “if p then” imply that p is true?

Thanks for the help form both of you!

Here’s the working script:

set IPServerAddress to "XXX.XX.XXX.XXX"
set volumeName to "G4Server"
set theUserName to "name"
set thePassword to "password"
try
	set p to word 4 of (do shell script "ping -c 5 -t 4 XXX.XX.XXX.XXX | grep transmitted") as number > 3 -- true if the G4 answers, false if less than 3 packets are received.
on error -- this is insurance just in case ping returns an error, which it did to me once
	set p to false
end try

tell application "Finder"
	if p is true then
		mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
	else
		set mountButton to button returned of (display dialog "The G4Server is not available for connection. 
To try again, please make sure the G4 is on and then click Retry.

If you would like to use your own computer to upload this art, click Mine. (NOTE: If you choose this option, the script will NOT send an email to the printer to notify them of the FTP upload.)

Click Cancel to quit." buttons {"Retry", "Mine", "Cancel"} default button {"Retry"})
		if mountButton is "Retry" then
			repeat while word 7 of (do shell script "ping -c 5 -t 4 XXX.XX.XXX.XXX | grep transmitted") as number > 3
				display dialog "The G4Server is still not responding.
Be sure the G4 is on and then click Retry or Cancel to exit this script." buttons {"Retry", "Cancel"} default button {"Retry"}
				set loopButton to the result
				if loopButton is "Cancel" then
					return
				end if
			end repeat
			mount volume volumeName on server IPServerAddress as user name theUserName with password thePassword
		else if mountButton is "Mine" then
			display dialog "The WorkStation script would now execute."
		else if mountButton is "Cancel" then
			return
		end if
		beep 3
	end if
end tell