Skip navigation

How to use Terminal output in Applescript

1671 Views 12 Replies Latest reply: Nov 11, 2012 12:54 PM by xaruqui RSS
xaruqui Level 1 Level 1 (0 points)
Currently Being Moderated
Oct 31, 2012 11:50 AM

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.

  • adayzdone Level 2 Level 2 (150 points)
    Currently Being Moderated
    Oct 31, 2012 12:19 PM (in response to xaruqui)

    "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"

  • MrHoffman Level 6 Level 6 (11,720 points)
    Currently Being Moderated
    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

  • adayzdone Level 2 Level 2 (150 points)
    Currently Being Moderated
    Nov 1, 2012 2:39 PM (in response to xaruqui)

    Again, "do shell script" does not work with Terminal. You can send a command to Terminal using "do script".

  • Camelot Level 8 Level 8 (45,670 points)
    Currently Being Moderated
    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).

  • adayzdone Level 2 Level 2 (150 points)
    Currently Being Moderated
    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. 

     

    2012-11-03 Screenshot 55.png

    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

  • Camelot Level 8 Level 8 (45,670 points)
    Currently Being Moderated
    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.

  • Camelot Level 8 Level 8 (45,670 points)
    Currently Being Moderated
    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

Actions

More Like This

  • Retrieving data ...

Bookmarked By (0)

Legend

  • This solved my question - 10 points
  • This helped me - 5 points
This site contains user submitted content, comments and opinions and is for informational purposes only. Apple disclaims any and all liability for the acts, omissions and conduct of any third parties in connection with or related to your use of the site. All postings and use of the content on this site are subject to the Apple Support Communities Terms of Use.