Getting Notified when a process is using 100% CPU on Mac OS X

Lately I’ve noticed node.js occasionally spawning a process that’s using 100% CPU. When this happens, the battery on my MacBook quickly drains.
17/08/2015 19:32:36.000 kernel[0]: process node[9119] caught causing excessive wakeups. Observed wakeups rate (per sec): 718; Maximum permitted wakeups rate (per sec): 150; Observation period: 300 seconds; Task lifetime number of wakeups: 45006
Now, I’ve not worked out what’s starting this node.js process, but I have my suspicions that it’s probably down to one of the plugins I’m using with Sublime.
So until I can work out what the cause is, let’s treat the symptom: node.js uses 100% CPU and shags my battery.
My solution is creating a daemon that shows a notification when a process is using 100% CPU, so I can then find it and kill it.
Install terminal-notifier (github)
$ brew install terminal-notifier
$ brew linkapps terminal-notifier
Create a script to check if the CPU is being excessively used by a process
I found a nice simple script on Stack Overflow, which does exactly what I want.
#!/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
So save this to somewhere, I saved mine in ~/bin/check100proc.sh
Now you need to make this script run periodically. This is done using launchdaemon.
Save the following plist somewhere, I saved mine in ~/Library/LaunchDaemons/com.omgmog.check100proc.plist.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.omgmog.check100proc</string>
<key>ProgramArguments</key>
<array>
<string>/Users/max/bin/check100proc.sh</string>
</array>
<key>StartInterval</key>
<integer>300</integer>
</dict>
</plist>
This plist will daemonise the check100proc.sh that you created earlier, to make it run every 5 minutes (or 300 seconds).
You’ll want to change the path to reflect wherever you saved the check100proc.sh.
Then load the plist with launchctl:
$ launchctl load -w ~/Library/LaunchDaemons/com.omgmog.check100proc.plist
That’s it. You can check that the plist has been daemonised and is running using the following command:
$ launchctl list | grep check100proc
Related posts
- Making GIMP feel less like punishment
GIMP has always had an interface problem. I’m not blaming the GIMP team (they’ve built something powerful on a shoestring). They’ve been clear they’re not interested in copying Photoshop wholesale; their FAQ argues that designing around actual user research beats imitating someone else’s interface decisions. Fair enough in principle, but coming from years as a Photoshop user, that design still feels hostile to me. I’m just one user story out of many they’ve had to design for, but it still expects me to learn its own way of doing things rather than offering a config closer to what I’m used to out of the box.
- Replacing the macOS audio switcher with SwiftBar
The built-in audio output menu in macOS has always felt a bit limited. The icons aren’t very helpful, the device names can’t be customised, and if you’ve got a few different outputs, it becomes tricky to quickly tell what’s what.
- Installing Chrome OS on a Late 2009 MacBook
I’ve got an old 2009 MacBook 6,1 (A1342) kicking about in my office that I’ve been playing with on and off lately.
Discussion
No interactions yet
Join the conversation
Reply from your own site with a Webmention (how?).
