Browse Tag: osx

long-running bash command notifier for osx

I stumbled across this fantastic blog post that offers a clever bash script to notify you of the completion of long-running commands in your bash shell. I made a couple tweaks to make it work for OSX, and gave it a little blacklist (I usually run `less’ or `vim’ for >10 seconds, for example).

Requires growl and growlnotify, bash, and this clever pre-exec hook for bash. Download that pre-exec hook:

mkdir -p ~/src/shell-tools
curl > ~/src/shell-tools/preexec.bash

Now copy and paste this into ~/src/shell-tools/long-running.bash:

# Source this, and then run notify_when_long_running_commands_finish_install
# Relies on
# Full credit to
# Modified slightly for OSX support and blacklist (see the egrep loop in the
# precmd() function

if [ -f ~/src/shell-tools/preexec.bash ]; then
    . ~/src/shell-tools/preexec.bash
    echo "Could not find preexec.bash"


function notify_when_long_running_commands_finish_install() {
    local RUNNING_COMMANDS_DIR=~/.cache/running-commands
    for pid_file in $RUNNING_COMMANDS_DIR/*; do
        local pid=$(basename $pid_file)
        # If $pid is numeric, then check for a running bash process.
        case $pid in
        ''|*[!0-9]*) local numeric=0 ;;
        *) local numeric=1 ;;

        if [[ $numeric -eq 1 ]]; then
            local command=$(ps -o command= $pid)
            if [[ $command != $BASH ]]; then
                rm -f $pid_file


    function precmd () {

        if [[ -r $_LAST_COMMAND_STARTED_CACHE ]]; then

            local last_command_started=$(head -1 $_LAST_COMMAND_STARTED_CACHE)
            local last_command=$(tail -n +2 $_LAST_COMMAND_STARTED_CACHE)

            if [[ -n $last_command_started ]]; then
                local now=$(date -u +%s)
                local time_taken=$(( $now - $last_command_started ))
                if [[ $time_taken -gt $LONG_RUNNING_COMMAND_TIMEOUT ]]; then
                  if [ `echo "$last_command" | egrep -c "less|more|vi|vim|man|ssh"` == 1 ] ; then 
                    exit 0
                    growlnotify \
                        -m "$last_command completed in $time_taken seconds" \
                        "Command complete:"
            # No command is running, so clear the cache.
            echo -n > $_LAST_COMMAND_STARTED_CACHE

    function preexec () {
        date -u +%s > $_LAST_COMMAND_STARTED_CACHE
        echo "$1" >> $_LAST_COMMAND_STARTED_CACHE


Finally, source it by adding the following to your ~/.bash_profile:

. ~/src/shell-tools/preexec.bash
. ~/src/shell-tools/long-running.bash

also: site redesign! (read: i installed a new theme from the gallery, go team)

SOLVED: Macbook Air kernel_task slowness

I love my Macbook Air more than I’ve loved any laptop before (my first experience with a 12″ iBook in 2005 was a thing of beauty, but pales in comparison to my relationship with my Air). However, its CPU throttling to prevent heat drives me batty due to its aggressiveness — play a Flash video, for example, for a few minutes and it will start stuttering as the CPU temperature rises. Let it continue and the entire computer will slow to a crawl. If you open Activity Monitor or look at top, you’ll see a process owned by root called ‘kernel_task’ using 150% CPU usage or so. Kill the Flash video and the kernel_task will slowly scale back and things will return to normal.

What’s going on here is an interesting approach to temperature management. As temperature rises due to load on the CPU, the kernel runs some low-cost operations over and over — think ‘gettimeofday()’-style functions. Since the kernel has top priority, system CPU usage spikes while userland CPU usage is forced down, lowering the actual activity that the CPU is doing and thus lowering the temperature. A decent idea, I guess, but in practice it’s way too aggressive.

Luckily, doing a bit of digging in /System/Library/Extensions, I came across an extension called ‘AppleIntelPenrynProfile.kext’ that, looking at the Info.plist, ties into power management and performance monitoring — the IOClass is ‘AppleIntelPenrynPerformanceMonitor’ and the IOProviderClass ‘AppleACPICPU’.

This kernel extension is loaded on boot into userland, but interestingly, if you boot into safe mode (hold shift during boot), it is not loaded — and the kernel_task CPU spikes don’t occur, even under heat-generating load. You can verify this by running `kextstat’, which lists all loaded kernel extensions — run it in Terminal while booted normally and you should see an extension called ‘’ loaded. Boot into safe mode by holding down shift before the chime and run `kextstat’ again — no, and no kernel_task CPU spike when generating heat (play a Flash video).

So… why load that module at all?

Back in normal OSX, launch Terminal and run the following:

cd /System/Library/Extensions/AppleProfileFamily.kext/Contents/PlugIns
sudo kextunload AppleIntelPenrynProfile.kext

Verify it’s unloaded:

kextstat | grep Penryn

This should return no output if the module was successfully unloaded. Now, go play a Flash video and enjoy a less-crippled Air!

* Disclaimer: I take NO responsibility if you brick your Mac, it catches on fire, never boots again, or otherwise break. I’ve had no problems and it’s been working quite well, but your experience/hardware/whatever may be different.

** Disclaimer 2: I highly recommend running SMCFanControl and pushing your fans to max when running heat-intensive operations. I do not recommend running your Air at 80ÂșC or hotter for extended periods — the kernel will no longer discourage this activity by slowing things down. It’s unlikely that you will fry your CPU due to extensive hot use, as the CPU’s thermal shutdown is lower than its point of combustion, but this doesn’t mean you should push that threshold.

*** Disclaimer 3: The Penryn profile is for the Rev 2 Macbook Airs. Rev 1 is Merom, with the extension called AppleIntelMeromProfile.kext.