Catch terminal error

HI,

I’ve just finished a script which allow me to

1- copy a folder to a new location
2- look in the new folder for .mhl files (which are xml like files with md5 and other info that can verify the integrity of
the copy)
3- run a terminal cmd to verify those .mhl
4- Once everything<s done, sent an email notification saying that the copy folder is ready.

Now, I’m looking for a way to catch errors in the .mhl verification (step 3) so that if the terminal encounter an error, the email won’t be sen, instead, a notification email (which can be define in the script) will be sent to another person to tell him to check the copy.

here’s the script I’m having so far

set sourceFolder to POSIX path of (choose folder with prompt "Choose a folder to copy:")
set targetFolder to POSIX path of (choose folder with prompt "And where do you want it to go?")
set {TID, text item delimiters} to {text item delimiters, "/"}
set sourceFolderName to text item -2 of sourceFolder
set text item delimiters to TID

property defaultGroups : {"Family", "Friends"}
property defaultLabels : {}

-- Prompt for the group to use
tell application "Contacts" to set everyGroup to name of every group
if (count of everyGroup) is greater than 0 then
	set theGroups to choose from list everyGroup with prompt ¬
		"Send this message to which group?" default items defaultGroups with multiple selections allowed
end if

-- Prompt for message subject
set theResult to display dialog "What would you like the subject of the message to be?" default answer ""
set theSubject to text returned of theResult

-- Prompt for whether an attachment is desired. If so, prompt for the location of the file.
set theResult to display dialog "Would you like to attach some files to this message?" buttons {"Yes", "No"} default button 1
set wantsAttachment to button returned of theResult
if wantsAttachment is equal to "Yes" then
	set theAttachment to choose file
end if

-- Prompt for message body
set theResult to display dialog "What would you like to say in the body of the message?" default answer ""
set theBody to text returned of theResult

-- Go through each account and constuct a list of possible addresses
-- to use as a return address for this message.
tell application "Mail"
	set listOfSenders to {}
	set everyAccount to every account
	repeat with eachAccount in everyAccount
		set everyEmailAddress to email addresses of eachAccount
		if (everyEmailAddress is not equal to missing value) then
			repeat with eachEmailAddress in everyEmailAddress
				set listOfSenders to listOfSenders & {(full name of eachAccount & " <") as string}
			end repeat
		end if
	end repeat
end tell

-- Prompt the user to select which account to send this message from.
set theResult to choose from list listOfSenders with prompt "Which account would you like to send this message from?" without multiple selections allowed
if theResult is not equal to false then
	set theSender to item 1 of theResult
	do shell script "/usr/bin/rsync -vautE " & quoted form of text 1 thru -2 of sourceFolder & space & quoted form of targetFolder
	set theFiles to paragraphs of (do shell script "/usr/bin/find " & quoted form of (targetFolder & sourceFolderName) & " -type f -name '*.mhl'")
	tell application "Terminal"
		if not (exists window 1) then reopen
		activate
	end tell
	repeat with aFile in theFiles
		tell application "Terminal"
			do script "mhl verify -f " & quoted form of aFile
			delay 1
			set frontWindow to window 1
			repeat until busy of frontWindow is false
				--sleep 1 (sorry, I find the script won't compile with this!)
			end repeat
		end tell
	end repeat
	tell application "Mail"
		
		-- Properties can be specified in a record when creating the message or
		-- afterwards by setting individual property values.
		set newMessage to make new outgoing message with properties {subject:theSubject, content:theBody & return & return}
		tell newMessage
			-- Default is false. Determines whether the compose window will
			-- show on the screen or whether it will happen in the background./3693.
			set visible to true
			set sender to theSender
			set theEmails to {}
			tell application "Contacts"
				repeat with aGroup in theGroups
					repeat with aPerson in people of group aGroup
						repeat with anEmail in emails of aPerson
							if (label of anEmail is in defaultLabels) or defaultLabels is {} then
								if theEmails does not contain the value of anEmail then
									copy (value of anEmail) to end of theEmails
								end if
							end if
						end repeat
					end repeat
				end repeat
			end tell
			repeat with anEmail in theEmails
				make new to recipient at end of to recipients with properties {address:anEmail}
			end repeat
			tell content
				if (wantsAttachment is equal to "Yes") then
					-- Position must be specified for attachments
					make new attachment with properties {file name:theAttachment} at after the last paragraph
				end if
			end tell
		end tell
		
		-- Bring the new compose window to the foreground, in all its glory
		activate
		send newMessage
	end tell
end if

Thanks a lot
Frederico

I have no idea what mhl is, but do you get an AppleScript run time error when you run the line without the terminal with

do shell script "mhl verify -f " & quoted form of aFile

or what kind of errors do you get ?

By the way, in Terminal

do script . in window 1

runs the script always in the frontmost window, so your window switching is not necessary

Hi Stefan,

I’m not getting any scripting errors per say. MHL files are files that contain the structure of the folder and MD% of all of the files that are in it. We’re using it to check if the copy integrity (no files missing or corrupted during copy). Once run in the terminal, if the check passes, nothing happen. But if the check fail, the terminal is showing the error

ex: Error: File does not exist: ‘/Users/fcengarle/Desktop/ZAP/Brown/ARRIRAW_FIles/A001R2BF/A001R2BF/A001C004_140528_R2BF.mov’

It’s those error that I want to catch. If a mho check fail, I want to be able to stop the script from sending the email saying that the copy is ready.

-F

Regarding this post,

I did some more research and it seems that the MHL tool I’m using have lis of exit codes. I’m now trying to capture those exit code but I haven’t succeed yet. If I can find a way to capture the exit code to say ‘‘if the exit code is not equal to 0 (which is the code for success)’’ then set a new mail notification and stop the script. I guess that can do the trick.

Any hint on how to get exit codes from a terminal command?

Thanks
Fred

AFAIK you can’t catch errors in Terminal.app unless you parse the contents.
In AppleScript environment without Terminal.app it’s very easy to trap the errors


try
	do shell script "do something"
	--  OK, result = 0
on error errorMessage number errorNumber
	--  Failed, result != 0, error code in errorNumber, message in errorMessage
end try

Thanks for the reply. Sa basically, instead go having the "do script “mhl verify -f " & quoted form of aFile” command I should find a way to do it in a shell script?

Why must it run in the Terminal.app?

You can send the output of a do shell script directly to your terminal window if that is what your want:

tell application "Terminal"
	set term to tty of selected tab of window 1
end tell

do shell script "echo 'this must be send to stdout of terminal window' >" & term

or you can send the stdout to TextEdit using by using the open command:

do shell script "echo 'this must be send to TextEdit' | open -fe"

Some commands does need to run in a terminal window but the difference between Terminal.app’s shell script and AppleScript’s built-in do shell script is an interactive shell vs. a non-interactive shell. So when an command needs a terminal window you can execute an new instance of bash with the option -i to execute a script in an interactive shell as it runs like in the terminal.

Thanks a lot Bazzie,

this seems to be working just fine :slight_smile: I did change the do script for this

	try
				do shell script "mhl verify -f " & quoted form of aFile
			on error
				set recipientErrorName to "WhiteHat"
				set recipientErrorAddress to "frederico.cengarle@visionglobale.com"
				set theErrorSubject to "error"
				set theErrorContent to "error"
				
				tell application "Mail"
					
					##Create the message
					set theErrorMessage to make new outgoing message with properties {subject:theErrorSubject, content:theErrorContent, visible:true}
					
					##Set a recipient
					tell theErrorMessage
						make new to recipient with properties {name:recipientErrorName, address:recipientErrorAddress}
						
						##Send the Message
						send
					end tell
				end tell
			delay 1
			set frontWindow to window 1
			repeat until busy of frontWindow is false
				--sleep 1 (sorry, I find the script won't compile with this!)
			end repeat
		end tell
end try
	end repeat

and it seems to work perfectly :-). There,s is two more little question that I’m having.

1- As you can see on my original script, first we’re asking for the folder to be copy and then for the email notification info to be sent once the copy and MHL verification pass successfuly. But now that I have an ‘‘on error’’ command, I would like to send a different set of email notification if error occurs. Now, everything seem to work fine when I try it with a successful copy (only the ''successful email is sent, the ‘‘error email is disregard’’), but when I try with a folder that failed MHL verification, the ‘‘error email’’ is sent but also the ''successful one. Question is, is there a way I can prevent applescript to continue after hitting some error (in order to only send the error mail notification and not the successful one)?

2- Also, the ‘‘on error’’ is set to detect error during MHL verification Now, the MHL verification tool as a set of exit code for different errors, do you know of a way to grab the exit code and parse it in the Error mail notification content? So that when one received the mail notification, he could know what is the error?

Thanks so much
Frederico

try
	do shell script "echo 'this is the error message' 1>&2; exit 50"
on error theMessage number theNumber
	return {theNumber, theMessage}
end try

In the code above I pipe my echo to stderr instead of stdout and exit the script with another number than 0 (to simulate your different return codes).