GeekTool DesktopThe past couple of days I’ve been playing around with GeekTool a nifty litlle application that can show text files, unix commands output (including scripts), or images (local and from the internet) on your desktop.  There are many sites with examples out there which inspired me to create a GeekTool setup of my own.

I started playing around with several scripts and GeekTool because it looked cool at first and it was fun to do some shell scripting. As the amount of information displayed on my desktop grew I started wondering why I was creating a lot of small processes taking up a little CPU time. I hardly ever look at my desktop because of all the windows in front of it. But the stats now on my desktop are easily accesable with one key (F11), and some starts are already displayed in either the menu bar or my iStat Pro widget. Removing it there gives me more room in the menu bar (which is starting grow full of icons) and saves some resources used by the widget.

Now I shall explain the GeekTool entries I created more detailed.

Battery

You can get a lot of information about your battery with the ioreg command. I found a battery status script which doesn’t work on leopard but with plenty of comment in the code to use it as a reference for the output of ioreg and write a little script of my own which prints the status, charge and time remaining. The code should be pretty self-explanatory.

#! /bin/sh
#
# Battery status script, writen by Ronald Chu for GeekTool usage. Free to
# use as you please.
#
# Prints the current charge, time remaining on battery power or the AC
# power status

# Create an array (Capacity, Voltage, Flags, Current, Amperage, Cycle Count)
# in 10.6 the order has changed to (Amperage, Flags, Capacity, Current, Voltage, Cycle Count) so we need to re-order
if [ -n '`sw_vers |grep ProductVersion:.10.6`' ]; then
  status=(`ioreg -w0 -l|grep LegacyBatteryInfo|sed -e 's/[^1234567890]/ /g'|awk '{print $3" "$5" "$2" "$4" "$1" "$6}'`)
else
  status=(`ioreg -w0 -l|grep LegacyBatteryInfo|sed -e 's/[^1234567890]/ /g'`)# Fix Amperage (convert large number to negative one)
  status[4]=$(expr ${status[4]} + 0)
fi

# if charger connected
if [ $((${status[2]} & 1)) == 1 ]; then
  #if battery is charging
  if [ $((${status[2]} & 2)) == 2 ]; then

    # Calculate minutes until  fullycharged
    if [ ${status[4]} -lt 0 ]; then
      mins=''
    else
      mins=`echo "(${status[0]}-${status[3]})*60/${status[4]}"|bc`
      if [ $mins -gt 59 ]; then
        mins=`printf ", %d:%02d until full" $(( mins / 60 )) $(( mins % 60 ))`
      else
        mins=`printf ", 0:%02d until full" $mins`
      fi
    fi
    echo `echo "${status[3]}*100/${status[0]}"|bc`"% (charging$mins)"
  else
    perc=`echo "${status[3]}*100/${status[0]}"|bc`
    if [ $prec -lt 100 ]; then
      echo "$perc% (not charging)"
    else
      echo "100% (charged)"
    fi
  fi

# if charger not connected
else
  # Calculate minutes until empty
  if [ ${status[4]} -ge 0 ]; then
    mins=''
  else
    mins=`echo "- ${status[3]}*60/${status[4]}"|bc`
    if [ $mins -gt 59 ]; then
      mins=`printf "(%d:%02d remaining)" $(( mins / 60 )) $(( mins % 60 ))`
    else
      mins=`printf (0:%02d remaining)" $mins`
    fi
  fi

  echo `echo "${status[3]}*100/${status[0]}"|bc`"%$mins"
fi

Hard disk

I only care about the free space on my main hard disk and not at all in what other drives, shares, disk images and so forth are mounted. So I filter and reformat output of df to show just that.

df -h | grep 'disk0s2' | awk '{print $4" free ("$5" of "$2" used)"}'

Memory

Calling top and extracting the memory usage is pretty simple. I am planning to extract much more information from top (like the load en processes using the most CPU time) later.

top -l 1 | awk '/PhysMem/ {print $8 " used, " $10 " free"}'

Network

I’ve written a bash script that takes the name of a network interface as a parameter and returns its status, IP address, the SSID if it is an airport connection and last but not least the amount of data sent and recieved. The comment in the code should explain everything.

#! /bin/sh
#
# Network status script, writen by Ronald Chu for GeekTool usage. Free to
# use as you please.
#
# Prints status, ip, trafic and (if aplicable) SSID name of the airport and
# ethernet connection. Network IO is stored with timestamp in milliseconds
# in a text file so with the difference in time and bytes the IO in bytes
# per second can be calculated.

workdir="/Users/ronaldchu/Applications/Scripts/GeekTool/"

# parameter is a number of bytes * 100 (for float precision)
function formatBytes()
{
  if [ $1 -lt 102400 ]; then echo `echo "scale=2; $1/100"|bc` b; else
    if [ $1 -lt 104857600 ]; then echo `echo "scale=2; $1/102400"|bc` Kb; else
      echo `echo "scale=2; $1/104857600"|bc` Mb;
    fi
  fi
}

# The script takes the name of the interface as a parameter
if [ $# -lt 1 ]; then
  echo "Parameter missing"
  exit 1
fi

# Check if interface exists
ifconfig $1 > /dev/null 2>&1
if [ $? -ne 0 ]; then
  echo "Interface \"$1\" does not exist"
  exit 2
fi

#Extract ip adress
ip=`ifconfig $1 | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}'`

if [ $ip ]; then

  # Make IO info string "
  IO_now="`${workdir}milliseconds` `netstat -ib | grep -e "$1" -m 1 | awk '{print $7" "$10}'`"

  # If there is an old IO info file
  if [ -f "${workdir}NetworkStatus_$1_IO.txt" ]; then
    IO_old=`cat ${workdir}NetworkStatus_${1}_IO.txt`

  # else create one and sleep for a second
  else
    echo $IO_now > ${workdir}NetworkStatus_${1}_IO.txt
    IO_old=$IO_now
    sleep 1
    IO_now="`${workdir}milliseconds` `netstat -ib | grep -e "$1" -m 1 | awk '{print $7" "$10}'`"
  fi

  #calculate IO trafic in Kb/s
  IO_in=`echo $IO_old $IO_now|awk '{print "scale=0; (100*("$5"-"$2"))/("$4"-"$1")"}'|bc`
  IO_out=`echo $IO_old $IO_now|awk '{print "scale=0; (100*("$6"-"$3"))/("$4"-"$1")"}'|bc`

  # Write current IO info
  echo $IO_now > ${workdir}NetworkStatus_${1}_IO.txt

  # Echo network status (with SSID iff the network interface is the airport)
  if [ $1 == "en1" ]; then
    SSID=`/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I|grep '[^B]SSID' |sed -e 's/^[^:]*: //'`
    echo "$ip ($SSID) `formatBytes $IO_in`/s down `formatBytes $IO_out`/s up"
  else
    echo "$ip `formatBytes $IO_in`/s down `formatBytes $IO_out`/s up"
  fi

else
  echo "Disconnected"
fi

To obtain the timestamp for the network data readings using date isn’t accurate enough, so I use the following little C program to get a more accurate timestamp.

#include <stdlib.h>
#include <sys/time.h>

main()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  printf("%d.%d\n", tv.tv_sec, tv.tv_usec);
}

Twitter

What else can I do? Well, whenever you want add something fancy you can always do something with Twitter! It makes you modern and Web 2.0, and stuff like that. Also it was extremely easy to add the latest tweets from my friends to my desktop with only one single command.

curl -u username:password http://twitter.com/statuses/friends_timeline.rss?count=20| \
grep title|\
tail -n 20 |\
sed -e 's/.*\(.*\)<\/title>/\1/'

iTunes

For information on the track currently playing in iTunes I’ve combined several scripts and ideas from others and myself to create an applescript which extracts the album art and returns the artist, title and album of the current song. Add another entry in GeekTool to show the image, which is a PNG file in a fixed location. In my case, this is located at file:///Users/ronaldchu/artwork.png

# iTunesCurrentSong.scpt
#
# An applescript which returns the title, artist, album and player
# status of iTunes and writes the current album art (or blank if
# iTunes not running, or a default image if no art available) to a
# png file
#
# Network status script, writen by Ronald Chu for GeekTool usage. Free to
# use as you please.

# folders specs
set artworkFolder to ((path to home folder) as text) & "Applications:Scripts:GeekTool:"
set artworkFile to artworkFolder & "artwork.png"
set artworkiTunes to artworkFolder & "artwork.pict"
set artworkBlank to artworkFolder & "blank.png"
set artworkDefault to artworkFolder & "default.png"
set unixArtworkFile to the quoted form of POSIX path of artworkFile
set unixArtworkiTunes to the quoted form of POSIX path of artworkiTunes
set unixArtworkBlank to the quoted form of POSIX path of artworkBlank
set unixArtworkDefault to the quoted form of POSIX path of artworkDefault

# Check if iTunes is running
tell application "System Events"
	set powerCheck to ((application processes whose (name is equal to "iTunes")) count)
	if powerCheck = 0 then
		# If there's no iTunes running use the Blank Arwork
		do shell script "cp " & unixArtworkBlank & " " & unixArtworkFile
		return ""
	end if
end tell

tell application "iTunes"

	# Get current track name and status
	try
		set playerstate to (get player state)
	end try
	if playerstate = paused then
		set trackPaused to "
"
	else
		set trackPaused to ""
	end if
	if playerstate = stopped then
		# If there's iTunes use the default Arwork.
		do shell script "cp " & unixArtworkDefault & " " & unixArtworkFile
		return "

"
	end if

	set trackID to the current track
	set trackName to the name of trackID
	set artistName to the artist of trackID
	set albumName to the album of trackID

	(* Is there any Artwork? *)
	if (count of artwork of trackID) ≥ 1 then
		set artworkData to data of artwork 1 of trackID
		set fileRef to (open for access artworkiTunes with write permission)
		try
			set eof fileRef to 512
			write artworkData to fileRef starting at 513
			close access fileRef
		on error errorMsg
			try
				close access fileRef
			end try
			error errorMsg
		end try

		tell application "Image Events"
			launch
			set theimg to open artworkiTunes
			scale theimg to size 100
			save theimg as PNG in artworkFile with replacing
			close
		end tell

	else
		(* If there's no Artwork use the default artwork. *)
		do shell script "cp " & unixArtworkDefault & " " & unixArtworkFile
	end if

	return trackPaused & "
" & artistName & "
" & trackName & "
" & albumName
end tell

For some reason the code contains html code for special character like < and &. I’ll look into this later, for now you just have to change that when copying the code. Also I’m having lot’s of difficulty with getting syntax highlighting working right, damnit…

Update 07/06/09: Changed the battery script so it will show “100% (charged)” instead of “100% (not charging)”.

Update 23/06/09: Please leave a comment if you like my scripts, or if you don’t. I’d love to get some feedback and know how many of the visitors google analytics reports to me are actualy using the scripts

Update 24/08/09: Updated the battery script, changed > to -gt to actualy do a greater-than comparisation instead of dumping into a file called 59.

Update 27/11/09: Added a version check to the BatteryStatus script because the order of the battery info has changed since 10.6

27 Responses to “GeekTool”

  1. I started playing with GeekTool at the weekend, and I am keen to use your excellent sounding battery script. After creating the script file how do you get it to run in GeekTool.

    I have just tried your twitter script and it appears untidy as it keeps the when it is displayed, can you remove the ?

    Cheers

    Steve

  2. Save the battery script in a text file (eg. ~/Applications/Scripts/BatteryStatus.sh) and make it executable. Then add the full path of the script in GeekTool as a Shell Command (eg. Users/yourname/Applications/Scripts/BateryStatus.sh.

    I have just tried your twitter script and it appears untidy as it keeps the when it is displayed, can you remove the ?
    What is untidy in the Twitter output?

  3. I like the iTunes script.
    How did you get the icons to work(battery?), or are they just part of the background?

  4. They are part of the background. I’ve considered placing them with geektool so the icons of the network connections won’t show if the connection isn’t active but that would take up more resources.

  5. The battery script is creating a text file titled “59″ at the root of my drive. Any ideas why?

  6. Because I used [ $mins > 59 ] which of course needs to be [ $mins -gt 59]. Thanks for pointing it out, it also explains the the unexplained ’59′ files on my hard drive :)

  7. Can’t get the network script to run. It is chmod’d to 777 and I get Parameter missing as the result. I’m missing something simple, I just know it

  8. Add the missing parameter, namely the name of your network interface, for example ./NetworkStatus.sh en1. Use ifconfig in your terminal to see active network connection(s) and their names.

  9. Hi. Thank you for your geektool codes. However, I’m having difficulty working on the iTunes artwork to be displayed on the desktop via GeekTool.

    Could you help please?

    Thanks

  10. Hi Ronald. I finally got it working (the iTunes script) but one thing I noticed is the refresh rate… If I set it to1 sec, the image flickers after every second. If I put higher number, the image doesn’t update.

  11. Perhaps if you set both entries to 1 sec the images flickers because it is being updated by the script? Refreshing of the image isn’t to great, I’ve set it to 10 sec but it can take up to 20 sec to display the correct image (first wait 10 sec for the script to run, than wait another 10 sec for the image to be updated). It’s not ideal.

  12. Hi,

    very cool scripts !!

    Your background image is very cool. May I ask where I can download this picture

    Thanks in advanced

  13. Hi,

    Good work.

    About your network script. When testing this in mac mini I got results like -1.31b/s down and -.31b/s up when transferring lot’s of data.

    #calculate IO trafic in Kb/s
    IO_in=`echo $IO_old $IO_now|awk ‘{print “scale=0; (100*(“$5″-”$2″))/(“$4″-”$1″)”}’|bc`
    IO_out=`echo $IO_old $IO_now|awk ‘{print “scale=0; (100*(“$6″-”$3″))/(“$4″-”$1″)”}’|bc`

    when i tried to echo these variables i got :

    bobby:geektool Booby$ echo $IO_old $IO_now
    1008427297 4261400953 1008440624 4261407891

    what are these variables $5 $6. Can you explain because I’dont understand.

  14. @erno Thanks, I’ve made that goat several years ago, you can download it at rchu.nl/files/eldiablo.png

    @Booby The $IO_old and $IO_now variables should contain three numerical values the first being the current UNIX time in miliseconds. Thats where the $5 and $6 variables come in. You’ve probably forgotten to compile the little C program listed below the network status script to return this time so the call to miliseconds fails.

  15. I forgot that, but when tried to compile your C script got many errors.
    cc -o test test.c

    what I should do that I can compile it right…

    Many thanks ;o)

  16. @erno I’ve tried CC and GCC the same way you did and both give me a warning (incompatible implicit declaration of built-in function ‘printf’), but it compiles and works anyway. I have practically no expericence with C and made that program with lot’s of googling and trail and error, so I can’t really help you more than this.

    You can get my compiled binary at http://rchu.nl/files/milliseconds, maybe that helps.

  17. My friend solve that problem, these lines top of that code and it works. Don’t know anything about C but now I got cool scripts working…

    #include
    #include
    #include
    #include
    main( )
    ….

  18. @erno That doesn’t make sense to me. I have little C skills but quite some programming skills so I could just misguess C syntax here… Anyway, cool that everything is up and running!

  19. I’m using your iTunes applescript with geektool 3 and it work great when I tunes is running and when current track has artwork. But it won’t change the artwork when iTunes quits and/or when the track has no artwork. Any suggestions?

    MBPro 15″
    OSX 10.6.1
    GeekTool 3.0 RC5 (116)

  20. thanks for the scripts.
    having trouble making the battery one work. it displays something like 283% when the battery is fully charged and the charger is connected. the value changes if the charger is disconnected and seems to be reflecting the actual changes. and yet, nothing but ’283%’ (or whatever the current value is) on the display

  21. @alex: I haven’t used the scripts since my upgrade to Snow Leopard, aparentely I don’t need GeekTool that much. Anyway, I noticed some strange behavior too and found out that since SL the order of the output of ioreg has changed. I’ve updated the script to detect SL and reorder if needed. It should work now.

  22. My network tracking stays at .15b/s down 1.17b/s up. Is there a way to fix this?

  23. @Jelmer I assume that you’ve tried generating lots of traffic, reset the connections and so forth. You could try to check the write permissions or just delete the NetworkStatus_*_IO.txt files which store the previous amount of data transmitted, though they should be updated each time the script runs.

  24. I’m having some problems with your battery script, What do I type into GeekTools Command line for it to echo the script onto the desktop?

    • @Eddie Save the script as a plain text file (e.g. ~/Applications/batterystatus.sh, the .sh extension, for shell script, is not required but common). Make it executable (chmod a+x ~/Applications/batterystatus.sh on the terminal, replace the filename with the location you chose) and then enter the full path to that file as the command of a shell item in GeekTool.

  25. you suck really why to make all your script so hard to understand -.- no one is working only disk use bla bla and of the ram. network does work

  26. How can I refresh geektool every millisecond???

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Spam protection by WP Captcha-Free

© 2011 Ronald! Suffusion theme by Sayontan Sinha