Submit Hint Search The Forums LinksStatsPollsHeadlinesRSS
14,000 hints and counting!

View valid 'top' output on the desktop via GeekTool UNIX
The great and free GeekTool (PowerPC | Intel) can write the contents of any file, and the output of any shell command, right onto the desktop. Unfortunately it doesn't support self-updating commands like top, and the official workaround (break the loop with top -lk and set Refresh to keep restarting it) is rather Heisenbuggy:
  1. Taking k = 1, the CPU usage line and column stop making sense.
  2. With k > 1, they become skewed by an overestimated CPU usage for top itself.
  3. Either way, relaunching top every few seconds soon causes pid's to roll over 30000, so that recent processes must be hunted down the list rather than conveniently appearing on top.
In short, watching top this way perturbs it more than we'd like. In this hint, I describe a different (k = 0) workaround which appears to solve the problem, i.e. display top exactly like Terminal does.

Here's how to do it:
  1. In the GeekTool Preference Pane, make a new entry top.log of type File, with Path set to /var/tmp/top.log. This will make GeekTool always display the last 50 lines of this file -- internally it runs tail -n50 -F on it.

  2. Make another new entry of type Shell, with Command: top.py, Size: 0 by 0, Refresh: 10. Actually, our script will run only once, but for some reason GeekTool gets far more CPU-intensive if the Refresh field is empty or zero.

  3. Put the following script, top.py, in ~/Library/Application Support/GeekTool Scripts. Be sure to make it executable by running chmod a+x on it, so it will execute.
    #!/usr/bin/env python
    
    import os, time
    
    os.system("top -l0 -n45 -s3 -S >> /var/tmp/top.log &")
    while True:
        open("/var/tmp/top.log","w").close()
        time.sleep(60)
    Here the os.system line spawns one top process, which forever (-l0) keeps sending 45 lines, every three seconds, to our top.log. The while loop then tames the log's growth by emptying it once a minute. Fewer than 45 lines works fine, but more seem to cause a jerky display.

  4. Now click Enable GeekTool, select the top.log entry, and customize the window to taste, moving it up so that the first (50 - 45 = 5) lines hide above the Mac menu bar. Close the Pref Pane, and compare the result with top -s3 running in Terminal.
In conclusion, let's hope that new releases of GeekTool will obsolete this hint, and let us also put things like fseventer on the desktop!
    •    
  • Currently 1.00 / 5
  You rated: 1 / 5 (5 votes cast)
 
[25,877 views]  

View valid 'top' output on the desktop via GeekTool | 15 comments | Create New Account
Click here to return to the 'View valid 'top' output on the desktop via GeekTool' hint
The following comments are owned by whoever posted them. This site is not responsible for what they say.
View valid 'top' output on the desktop via GeekTool
Authored by: mark hunte on Aug 09, '06 07:42:07AM
I've used
top -u -FR -l2 | grep -v 0.0% | grep % | grep -v Load | grep -v COMMAND | cut -c 7-24
with a refresh of 2 seconds, worked fine for me. Did not notice a PID issue but then when I used it I would not have looked for it.

---
mh

[ Reply to This | # ]

View valid 'top' output on the desktop via GeekTool
Authored by: mark hunte on Aug 09, '06 07:55:44AM

Just re ran mine and I see what you mean...

---
mh



[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: jaysoffian on Aug 09, '06 06:11:23PM

You're not actually shrinking the log file. Even though you're truncating it with the python script, the top process's stdout file-descriptor maintains its position in the log. Hence when top produces new output the beginning of the log is filled with null bytes. Try this test. Open two terminal windows. In the first terminal window, simulate your top process with:

sh -c 'while :; do echo hello; sleep 1; done' >> /tmp/foo

Wait about 10 seconds.

Now in your second terminal window:

sh -c '>/tmp/foo'

Wait at least second and then kill the original "hello" process.

Now do an "od -a /tmp/foo" and notice the file is filled with nul bytes.

j.





[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: hysterion on Aug 09, '06 08:14:20PM
> "You're not actually shrinking the log file."

Well, I may be wrong, but believe it or not I did check this :-) I suggest you check your theory on the given script and not on a different one. Here then is what you get if you watch the log's growth:


$ while true; do ls -l /var/tmp/top.log; sleep 15; done
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:52 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  40180 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  56252 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  0 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  40181 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  56253 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  0 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:54 /var/tmp/top.log
^C
i.e. the size does shrink to zero once a minute. (You can also see this by opening the log in Console.app with a double click.) What you are describing is what would happen if I had used ">" in place of ">>" in the script's os.system line.

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: hysterion on Aug 09, '06 09:03:09PM
> "Now do an "od -a /tmp/foo" and notice the file is filled with nul bytes."

Not on my machine:


$ sh -c 'while :; do echo hello; sleep 1; done' >> /tmp/foo
^C
$ od -a /tmp/foo
0000000    h   e   l   l   o  nl   h   e   l   l   o  nl                
0000014
(I've done as you say in the other Terminal.)
On the other hand, as I mentioned above, with ">" in place of ">>" you would get

$ sh -c 'while :; do echo hello; sleep 1; done' > /tmp/foo
^C
mini:~ fz$ od -a /tmp/foo
0000000  nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul nul
*
0000100  nul nul   h   e   l   l   o  nl   h   e   l   l   o  nl        
0000116
I hope this clears it up! (I'd rather keep the 5-line script than switch to one that makes 25...)

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: jaysoffian on Aug 09, '06 07:44:53PM
Here is an alternate python script that does what you want:

#!/usr/bin/python
import os, sys
from fcntl import fcntl, F_SETFL
from posix import O_NONBLOCK
from select import select

log = open("/var/tmp/top.log", "w")
top = os.popen("top -l0 -n45 -s3 -S")
top_fd = top.fileno()
fcntl(top_fd, F_SETFL, O_NONBLOCK)
_buf = ""
#clear = os.popen("clear").read()
while 1:
	fds, junk1, junk2 = select([top_fd], [], [], .5)
	if top_fd not in fds: continue
	buf, _buf = _buf, ""
	buf += top.read()
	if buf.endswith("\n"):
		if buf[0] == "\n": buf = buf[1:]
#		sys.stdout.write(clear + buf)
		log.seek(0)
		log.write(buf)
		log.truncate()
		buf = ""
	else:
		_buf = buf

This is slightly complicated because 45 lines of output is just *a byte or two* over 4k which is the popen buffer size, so the reads were getting output split across each emission from top. If you use 44 lines then the program can simplified a bit, but hey, here's something that works with any line count. :-)

Next change your geek tool command from File to Shell and make it simply:

cat /var/tmp/top.log

Note that there is nothing which prevents cat from getting a completely empty file if it reads at the wrong time, but that doesn't seem to happy too often for me.

j.

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: jaysoffian on Aug 09, '06 08:10:47PM
Here's a small optimzation with a different invocation of top. No need to limit top's output to 45 lines, -F to less its CPU load, and different sorting. Also don't need the timeout in the select():
#!/usr/bin/python
import os, sys
from fcntl import fcntl, F_SETFL
from posix import O_NONBLOCK
from select import select

log = open("/var/tmp/top.log", "w")
top = os.popen("top -l0 -s3 -S -F -ocpu -Otime")
top_fd = top.fileno()
fcntl(top_fd, F_SETFL, O_NONBLOCK)
_buf = ""
#clear = os.popen("clear").read()
while 1:
	fds, junk1, junk2 = select([top_fd], [], [])
	if top_fd not in fds: continue
	buf, _buf = _buf, ""
	buf += top.read()
	if buf.endswith("\n"):
		if buf[0] == "\n": buf = buf[1:]
#		sys.stdout.write(clear + buf)
		log.seek(0)
		log.write(buf)
		log.truncate()
		buf = ""
	else:
		_buf = buf



[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: hysterion on Aug 09, '06 08:11:21PM
> You're not actually shrinking the log file. Well, I may be wrong, but believe it or not I did check this :-) I suggest you check your theory on the given script and not on a different one. Here then is what you get if you watch the log's growth:

$ while true; do ls -l /var/tmp/top.log; sleep 15; done
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:52 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  40180 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  56252 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  0 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:53 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  40181 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  56253 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  0 Aug  9 22:54 /var/tmp/top.log
-rw-r--r--   1 fz  wheel  20090 Aug  9 22:54 /var/tmp/top.log
^C
i.e. the size does shrink to zero once a minute. (You can also see this by opening the log in Console.app with a double click.) What you are describing is what would happen if I had used ">" in place of ">>" in the script's os.system line.

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: jaysoffian on Aug 09, '06 11:21:46PM

Indeed you're correct. Opening with ">>" uses O_APPEND which apparently causes the system to seek to the end of the file on each and every write, not just the first.

I thought I used >> in my test, but apparently I used >.

I guess you learn something every day. :-)

j.



[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: boli on Aug 12, '06 08:05:53AM
Hmm, why not use a non-refreshing command like ps instead? It can be customized to show anything you'd like, for an example see: My geektool tips

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: moxieboy on Aug 22, '06 07:31:04AM
I use a command leeched from the fabulous iStatPro widget...

ps -arcwwwxo "pid %cpu command" | egrep "PID|$1" | grep -v grep | head -12 | tail -11
Yields the following:

 2630   3.7 FolderShare
 4578   3.7 OmniWeb
   65   3.5 WindowServer
 4711   2.5 Microsoft Entourage
 7103   2.3 Terminal
   87   1.4 SystemUIServer
 7107   0.2 -bash
  126   0.1 Quicksilver
  175   0.1 mds
   69   0.1 ATSServer
 6757   0.1 mdimportserver
Elegant, simple, and you can set the refresh in GeekTool.

[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: killer54291 on Apr 11, '10 03:46:58PM

Thanks for sharing the command but it there any way to remove the pid? I don't care about pids, just process names and their cpu usage.



[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: killer54291 on Apr 11, '10 04:00:09PM

disregard my last comment, i figured that out. but is there any way to show vsize in megabytes instead of bytes? the current command is
ps -arcwwwxo "%cpu vsize command" | egrep "PID|$1" | grep -v grep | head -12 | tail -11

but that shows
1.1 22222222 command
2.2 33333333 command
3.3 44444444 command
etc.

and i want
1.1 22M command
2.2 33M command
3.3 44M command
etc.



[ Reply to This | # ]
View valid 'top' output on the desktop via GeekTool
Authored by: atomicham on Dec 20, '06 09:43:54PM

I just came across this while trying to find the answer. Finally, after seeing this tip with a python script, I crafted a single bash line:

l=`top -l1 -n20 | wc -l` && top -l2 -n20 -o cpu | tail -n${l}


This runs top a first time to figure out how many lines there are (I limit it to 20 processes, you can change that), it then does top with 2 updates (the second being the correct one) and cuts off the top half.



[ Reply to This | # ]
Here are my 2 useful ones
Authored by: Lectrick on Jan 25, '08 02:20:14PM

Along with viewing the system.log (leopard) or console.log (tiger)... I have views set up for these 2 outputs:

Memory Pigs

top -orsize -FR -l1 | grep % | grep -v Load | grep -v COMMAND | cut -c 7-19,64-69

CPU Hogs

top -u -FR -l2 | grep -v 0.0% | grep % | grep -v Load | grep -v COMMAND | cut -c 7-24


---
In /dev/null, no one can hear you scream



[ Reply to This | # ]