How to use Terminal output in Applescript

Hi,


I can't figure this out. I've been trying different commands but I always get the same output from Terminal. I want to check if a process is running, and if it's not, launch it. The problem is I got stuck at the first step.


tell application "Terminal"

activate

set exitstatus to do shell script "ps ax | grep httpd 2>&1"

if exitstatus is equal to 1 then


display dialog "Status number 1"

else

display dialog "Status number 2"

end if

end tell


What am I missing?


Thanks.

Posted on Oct 31, 2012 11:50 AM

Reply
12 replies

Nov 1, 2012 3:45 PM in response to xaruqui

You're dealing with your exit status incorrectly.


The issue is that do shell script always, always, always expects an exit status of 0 (success). However, grep returns a different status code - 1 if no lines were found.


In do shell script's case, an exit code of 1 is an error, and so it stops the script to report the error.


If you want to catch the error code, the easiest way is via a try statement:


try

do shell script "ps -A | grep -v grep | grep httpd"

display dialog "HTTPD is running"

on error


-- we get here if the previous command fails


-- i.e., in this case, if grep returns 1 (not found)

display dialog "Status Is 1 (httpd not running)"

end try


In this case, the do shell script runs. If it succeeds (grep finds the text) then it displays the 'HTTPD is running' dialog. If grep fails (it can't find the text) it returns an exit code that triggers the 'on error' block.


Note that this approach is somewhat peculiar to grep, since it returns an exit code that you're trying to respond to. Normally do shell script will return stdout (the output of the command) rather than just the error code, but in this case grep's output would be empty since the text doesn't exist

The other approach, which works if you want to capture the exit code is something like this:


set exitCode to do shell script "ps -A | grep -v grep | grep -q httpd; echo $?"


display dialog "Status is " & exitCode


Note the use of grep's -q (quiet) switch to suppress errors and the use of 'echo $?' to return the exit code of the last-executed command (and you still don't need Terminal.app).

Nov 3, 2012 2:40 PM in response to xaruqui

First of all, I tried "do script ..." but it didn't work for me, so I tried "set exitstatus to do shell script "ps ax | grep httpd" as you said with no success. I did understand what you said, but I had to try both commands.


My response was meant to show you that the "do shell script" scripting addition command does not belong to the Terminal Suite. Although you say you understand what I said, your second response includes "do shell script" within a tell application "Terminal" block.


User uploaded file

You still needed to write the code to deal with the information returned from the shell after you sent the command. One solution is to elimate the extra lines as Camelot shows. In his example the response needs to be handled within an error handler.


You could have used my answer like this:


set xxx to every paragraph of (do shell script "ps -ax | grep httpd")

if (count of xxx) > 2 then

display dialog "HTTPD is running"

else

display dialog "Status Is 1 (httpd not running)"

end if

Oct 31, 2012 12:28 PM in response to xaruqui

Your example is obviously looking for the Apache daemon. If you're looking to have that (or most other daemons) started or restarted and running, then the launchd can do that sort of thing for you. There are various launchd examples posted around the 'net, and a tool such as Lingon can make managing the launchd plist files (much) easier.


And FWIW, your grep command will find and match itself in the process list.


There are various ways to avoid this, but here's the brute-force approach:


$ ps -A | grep -v grep | grep httpd

Nov 1, 2012 1:44 PM in response to xaruqui

Thank you both, but there's still something wrong about it. I run:


tell application "Terminal"

activate

set exitstatus to do shell script "ps -A | grep -v grep | grep httpd"

if exitstatus is equal to 1 then

display dialog "Status number 1"

else

display dialog "Status number 2"

end if

end tell


...and I get status number 2, but If I write httpddd (some unknown process which is not obviously running) Applescript cancels itself telling that it cannot continue because is different to zero.


MrHoffman, I'm just testing with process httpd but my goal is quite different. Thanks anyway for telling me about launchd.

Nov 3, 2012 5:39 AM in response to xaruqui

Works like a charm!


Adayzdone, I tried just what you said:


"do shell script" does not work with Terminal. You can send a command to Terminal using "do script". Or you can simply use:

set exitstatus to do shell script "ps ax | grep httpd"



First of all, I tried "do script ..." but it didn't work for me, so I tried "set exitstatus to do shell script "ps ax | grep httpd" as you said with no success. I did understand what you said, but I had to try both commands.


Now, I realize what I was looking for is "on error ..." Very nice piece of command.


Thank you all for your help.

Nov 4, 2012 8:54 AM in response to xaruqui

You're right, I didn't notice and I kept using 'Tell application "Terminal"' altough I didn't run any command on it.


Now I realize I'm stuck again. I got to make it work (thanks to you guys) but I have to run this command in a logged SSH session. I have to log in (Terminal window) and run the command in the same window, so I'm forced to use "do script" instead of "do shell script" as you pointed earlier.


It won't work for me, either I get right script output in different windows or I work in the same window with wrong outputs.


tell application "Terminal"

activate

do script "ssh -t root@172.16.1.106 -p 22" in front window

delay 2

tell application "System Events"

keystroke "passwd" & return


delay 1

end tell

set ExitCode to do script ("ps -A | grep -v grep | grep httpd") in front window

delay 1

display dialog "Exit code:" & ExitCode

end tell


I'm trying to catch the output to work with it. I've tried "if 0", "if false", "on error", etc... Definitely, I didn't understand terminal outputs!

Nov 4, 2012 10:38 AM in response to xaruqui

OK, that radically complicates things. However you still have multiple options.


First off, is the server a Mac? There are other options for executing commands on a remote Mac.

Secondly, even if you do need to use SSH, you should shy away from logging in as root. There's nothing in this command that requires root-level privileges.


Thirdly, even if you do use ssh there's no absolute requirement to use Terminal.app - you should look at setting up private keys on the server, which will allow you to log in via SSH without needing an interactive password.


Fourthly, even if you do decide you need to use Terminal.app, your code is wrong 🙂


The issue is what 'do script' returns. Looking at the app's dictionary you see:


do script (verb)Runs a UNIX shell script or command. (from Terminal Suite)

function syntax

set theResult to do script text ¬
in tab, window or anything

result

tabThe tab the command was executed in.


Note the result is the tab that the command was executed in. It's not the output of the last command executed in that window - it's a reference to the tab. You have to query that tab to find out what content is in its widow, and process that text to find the output of your command.


Your best hope here is that the server is a Mac and you can use Remote Apple Events to target the remote system


tell application "System Events" of machine "epcc://ip.of.remote.machine"

set remoteProcessList to do shell script "ps -A"

end tell


if remoteProcessList contains "httpd" then


-- Apache is running

end if


Note that I've also taken a slightly different approach, which is to have the shell script just grab the process list and use AppleScript logic to determine if httpd is running - that avoids the whole issue with grep's output if the text doesn't exist.

Nov 6, 2012 12:14 PM in response to xaruqui

Well, that's discouraging. I loved the "epcc://ip.of.remote.machine" thing (I'll keep it in mind) but the server is not a Mac, and I don't want to set up private keys for that matter.


I tried my own non-professional approximation copying the output to the clipboard, but I don't know how to search text inside the clipboard "set counter to the count of word "httpd" in clipboard" didn't work. My current script looks like this:



tell application "Terminal"

activate

set FrontTab to do script "ssh -t user@172.16.1.103 -p 22" in front window

delay 2

tell application "System Events"

keystroke "passwd" & return


delay 1

end tell

activate

do script "ps -A | grep httpd" in front window

delay 0.5

tell front window to set the clipboard to contents of selected tab as text

#set counter to the count of word "camelot" in clipboard

end tell

Nov 6, 2012 3:41 PM in response to xaruqui

There's never a need to copy the result to the clipboard.


In this case, if you're really resigned to using Terminal.app then you can save yourself a lot of grief and use grep's -c (count) switch.


The problem with trying to count the number of occurrences of 'httpd' is that, at least on my machine, the ps output looks like:

$ ps -A | grep httpd

97275 ?? 0:06.35 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/httpd_server_app.conf

97278 ?? 0:00.63 /usr/sbin/httpd -D FOREGROUND -f /Library/Server/Web/Config/apache2/httpd_server_app.conf

32646 ttys002 0:00.00 grep httpd


How many 'httpd's do you see? I see 5 - one in the grep statement, and two in each of the process lines. While it is possible to do text parsing in AppleScript you have to take into account variances like this.


In contrast, grep -c httpd returns the number of lines that contain the string:


$ ps -A | grep -c httpd

3


That's a much easier answer to parse.


Now it should just be a matter of getting the text of the tab and grabbing the relevant line:


tell application "Terminal"

set theTab to do script "ps -A | grep -c httpd"


delay 1

tell front window to set theText to contents of selected tab as text

set httpd_process_count to (paragraph 3 of theText) - 1

end tell

Nov 11, 2012 12:54 PM in response to xaruqui

Hi, Camelot


Sorry for my delayed answer. I tried what you proposed, but I get an error telling me that you can't substract 1 from httpd_process_count. I guessed you wanted to skip last paragraph, so I wrote:


set httpd_process_count to (paragraph 2 of theText)


Since there are only two ocurrences of the process I want to monitor, I'll always get the process count.


Thank you very much for your help. You are a master.

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

How to use Terminal output in Applescript

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.