joe codes

x-cart guru & custom programmer

  • About
  • Archives
  • Contact

Powered by Genesis

Bad App Alert

August 10, 2017 by joecodes Leave a Comment

Bad App Alert? You could take this to mean that I’m alerting you of a problem with an app or that I’m showing you how to be notified when an app is behaving badly. It’s a little of both.

UPDATE: Added extra note under Save the Script for adjusting script to open an app when clicking on the notification.

I use Apple’s Notes constantly on Mac and iPhone since it can store in the cloud, appearing instantly on any device, and has new features like folders, multimedia, and security. However, on Mac it regularly freaks out for no apparent reason, going to 100% CPU without stopping, and must be force quit. While annoying, it’s not difficult to deal with.

However, I hate that it tries to destroy the computer until I stumble across the situation. Often I return to my MacBook to find it hot to the touch and I immediately know who the likely culprit is so I glance at smcFanControl in the menu bar to confirm the CPU temperature is way too high. I fire up Activity Monitor to find Notes using 100% CPU and force quit it. Excessively long high temperatures and prolonged CPU usage are probably not great for the computer if it’s not actually doing anything for that brief time then stopping. Or sometimes on battery power I realize too late that all of my portable work time is gone. It would be nice to be notified when an app is behaving badly instead of waiting to happen across it later.

Based on the excellent answer to a StackExchange question, I came up with the following to get a notification if any app started using too much CPU:

1. Save the Script

First step is to get the script from the link above. Here is a copy of it for reference:

#!/bin/bash
 
cpulimit=50
prefix=${TMPDIR}cron_cpu
current=$(ps -erco %cpu,command | tail -n+2 | sed 's/^ *//')
echo "$current" > $prefix$(date +%s)
a=($prefix*); for ((i=0;i<=${#a[@]}-3;i++)); do rm "${a[i]}"; done
[[ $(awk '{s+=$1}END{printf "%i",s}' <<< "$current") -lt $cpulimit ]] && exit
averages=$(awk '{cpu=$1;sub(/[^ ]+ /,"");a[$0]+=cpu;c[$0]++}END{for(i in a){printf "%.1f %s\n",a[i]/c[$0],i}}' $prefix* | sort -rn)
if [[ $(awk '{s+=$1}END{printf "%i",s}' <<< "$averages") -ge $cpulimit ]]; then
    terminal-notifier -title "CPU use" -message "$(head -n5 <<< "$averages" | paste -sd / -)"
fi

I saved mine as “cpuwatch.sh” in my handy scripts folder.

After using this for a while I found myself wanting to click on the notification to see more details. I wanted it to take me directly to Activity Monitor so I changed the terminal-notifier line in the script to this (adding -activate to the end):

    terminal-notifier -title "CPU use" -message "$(head -n5 <<< "$averages" | paste -sd / -)" -activate 'com.apple.ActivityMonitor'

2. Get Terminal Notifier

The simplest way I got Terminal Notifier was with the following Terminal command from their page:

$ [sudo] gem install terminal-notifier

3. Add PATH to the Script

The previous step installed terminal-notifier into /usr/local/bin. While the script worked fine this way in Terminal, it needed to know where to find Terminal Notifier when running automatically so this line was added to the script:

export PATH=/usr/local/bin:$PATH

4. Add to launchctl

To automate this we needed to add this to launchctl. The simplest way is to create a new job with something like LaunchControl.* Just add the path, add a Start Interval (I used 60 seconds), and optionally add a Standard Output to look for any errors with the script or this setup (this is how I found the PATH issue). *See Startup Item Help for an expanded discussion about adding to launchctl.

You’re done! Now if an app is using a lot of CPU you’ll get a notification. If notifications get too annoying I may bump up the threshold in the script, but hopefully Apple will update Notes soon before it eats my MacBook.

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)
  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to email a link to a friend (Opens in new window)

Related

Filed Under: Programming Tagged With: Apple, stability

Leave a Reply Cancel reply

You must be logged in to post a comment.

Quick Thoughts

  • I was surprised to learn that foreach in JavaScript does not have a traditional break. The loop will run to completion.

  • Who knew that combination sums across all permutation lengths of an array would be so difficult? It was a challenge but the final product looks good and takes a lot of resources. Limiting the max length for basic memory limits. Would only do something like this for occasional reporting.

  • Working on a new project that can have hundreds of forms on a page. The browser was spending way too much time in Parse HTML. Wasted a bunch of time before learning this is a long-standing bug in Chrome when there are many forms or inputs. Other browsers are fine.

Recent Posts

  • Parting Ways with OWC
  • MacBook External DVD Player
  • Progressive Enhancement
  • Keychain Password Search
  • Smarty preg_match

Tag Cloud

Apple JavaScript Mason Perl PHP security simple Smarty speed stability Tax WWDC X-Cart

Search

Subscribe

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Recent Comments

  • Bad App Alert on Startup Item Help
  • iPhone Pre-Order Needs to Change on iPhone Pre-Order Warning
  • Apple vs Pro on My Personal Three S’s of Development