[futurebasic] Re: OSX Utlity watches running application

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : February 2004 : Group Archive : Group : All Groups

From: Ken Shmidheiser <kshmidheiser@...>
Date: Thu, 12 Feb 2004 08:03:19 -0500
Micahel Evans asked:

>I would like to create an fb osx utility that watches selected running
>applications (processes?). If the app crashes/freezes some options would be:
>
>(1) Send an e-mail to the sysop
>
>(2) Force-quit the offending app and restart it
>
>(3) If (2) does not work, reboot the machine
>     (a) I have an applescript that auto-mounts servers.
>     (b) Presumably, if the user has entered (order is important here) first
>         the mount-servers applescript and next the selected applications
>         in the system preferences>accounts>startup items dialog, rebooting
>         would trigger evrything to work as before.
>
>(4) Perhaps someone has already written something like this that
>     is already available or foe sale. Any ideas, pointers, suggestions
>     would be cheerfully accepted...
>
>A shareware app AppTracker 3.0.1 watches selected applications and logs
>running times for billing purposes. That's a start..., but I want more....
>
>I would much prefer an fb app that I can add features, or change at will...


Michael:

If we can safely make these assumptions:

1.) The machines you are using are all running OS X;
2.) They are networked and/or you have an account on each machine

then you have several options.

If you want to control the entire network from a single master Mac,
you can monitor and execute commands remotely. Otherwise, you can
write an application to run independently on each Mac, e-mailing
notification of problems to you.

The first thing is to write some code to monitor the processes.
Here is a sample you can run on your machine. It utilizes Robert Purve's
PollTime Include to fire at a set interval-- every five seconds
in the demo code. (You can strip out the PollTime stuff if you just
want to run it one time.) This code returns a table of all the processes
running on your Mac at the time it was executed in the form of:


----------------------------------------------------
ApplicationName   PID   %CPU   %Mem   TimeUp   User
----------------------------------------------------


'------------ BEGIN PROCESS MONITOR CODE ---------


include "Subs PollTime.Incl"

begin globals
dim as container gC
end globals

local fn DoUnixCommand$( cmdStr as str255 )
dim as str255 tempStr, resultStr

open "unix", 2, cmdStr
do
line input #2, tempStr
gC += tempStr + chr$(13)
until eof (2)
close  2

end fn

local fn ProcessMonitor$
// For extended info use:
// end fn = fn DoUnixCommand$( "ps aux -c | grep -v root" )
// See the ps man pages for flags like those used below
end fn = fn DoUnixCommand$(¬
"ps ax -o command,pid,pcpu,pmem,time,user -c | grep -v root" )

local fn DoDialog
if dialog(0) = _wndClose then end
end fn

on dialog fn DoDialog

dim as rect  r
dim as str15 t
t = "Process Monitor"
setrect( r, 0, 0, 380, 400)
appearance window 1,t,@r,_kDocumentWindowClass,_kWindowCloseBoxAttribute
def SetWindowBackground( _kThemeActiveDialogBackgroundBrush,_zTrue)
text _courier, 10
setrect( r, 20, 20, 344, 380)
edit field 1,"",@r, _framedNoCR_usePlainFrame_noDrawFocus,_leftJust
setrect( r, 344, 19, 360, 381)
scroll button -1,0,0,0,0, @r, _scrollOther

fn SetupPollTime( 5000, _false ) //Poll time fires every 5 seconds

do
long if fn PollTime
fn ProcessMonitor$
edit$(1) = #gC : gC = ""
setselect 0, 0 : edit field 0
end if
handleevents
until 0


'------------END CODE---------------------


Using the table supplied by this code, you can parse out the performance
of the particular application you want to monitor, perhaps by putting
each line into an array and then parsing the individual elements for the
info you want. If that app is performing badly-- perhaps hogging CPU
cycles or Memory-- or appears to have stalled, you can easily quit it
by parsing out its PID (process identification) number from the table,
and feeding that number to the following function. (Note: Many of the
following functions call fn DoUnixCommand$):



local fn KillProcess$( pidStr as str15 )
end fn = fn DoUnixCommand$( "kill 9 " + pidStr )



To relaunch the application, you can use the following:



local fn LaunchApplication$( pathToAppStr as str255 )
end fn = fn DoUnixCommand$( "open -a " + pathToAppStr )

// Here's a little test you can run that will launch TextEdit
fn LaunchApplication$( "/Applications/TextEdit.app" )



To see if the application launched successfully, you could reexamine
the process table above. If not, you could restart the Mac with:

local fn RebootOX$
end fn = fn DoUnixCommand$( "reboot" )


or, alternatively:


_kAERestart = _"rest"
local fn DoOSXRestart
sendAppleEvent _kCoreEventClass, _kAERestart, _nil, _nil, "loginwindow"
end select
end fn


You already have the reboot startup configured so the machine should
come back online at which time you can also launch your Process Monitor
application and start all over.


If you wanted to run any of these code snippets from your master Mac
on a remote machine, you could execute the commands with a remote login
using the rsh command configured something similar to these samples,
depending on whether or not your user name was the same on both your
master Mac and the remote, in which case you use the first example or,
if your user name is different, you use the second:


local fn RemoteProcessMonitorA$( userName as str31 )
dim as str255 cmdStr

cmdStr  = "rsh " + userName
cmdStr += " ps aux -c | grep -v root"

end fn = fn DoUnixCommand$( cmdStr )


or


local fn RemoteProcessMonitorB$( remoteHost as str31, userName as str31 )
dim as str255 cmdStr


cmdStr  = "rsh " + remoteHost
cmdStr += " -l " + userName
cmdStr += " ps aux -c | grep -v root"

end fn = fn DoUnixCommand$( cmdStr )



To find remote hosts you can communicate with in such a way
on your network, you can run:



local fn FindHostsOnMyNetworK$
end fn = fn DoUnixCommand$( "cat /etc/hosts" )



Finally, a here is a function that sends a short e-mail message.
It depends on OS X's Unix "mail" command being activated by sendmail
or postfix. For activation details see:

http://www.versiontracker.com/dyn/moreinfo/macosx/21479



local fn QuickEmail$( msgTxt as str63,¬
                  subject as str15,¬
                   address as str31 )
dim as str255 cmdStr

cmdStr  = "echo """ + msgTxt
cmdStr += """ | mail -s """ + subject
cmdStr += """ " + address

end fn = fn DoUnixCommand$( cmdStr )

// Use like this:
fn QuickEmail$( "Hello", "Test", "johnsmith@..." )



There are several other approaches for automatic e-mail notification,
but this response is already too long.

Perhaps this will provide some food for thought.

Ken