2

System: MacBook Pro (early 2013), running up-to-date Mojave.

To analyze CPU utilization when an application is running I'm doing the same I've done over and again in a Linux system; running the following command on terminal:

top | grep idle

This works as it should, screen output is:

MacBook:Desktop Peregrino69$ top | grep idle
CPU usage: 13.14% user, 15.97% sys, 70.87% idle
CPU usage: 10.94% user, 8.53% sys, 80.52% idle
CPU usage: 10.95% user, 6.94% sys, 82.9% idle

However if I do

top | grep idle | tee ./utilization.txt

... unexpectedly there's no terminal output at all, and the resulting file is empty. This failing I tried

top | grep idle >> ./utilization.txt

... with the same result.

Testing redirection with a simple echo command echo hello | tee foo works as expected; the word "hello" outputs both on screen and in foo.

What's going on?

  • I'm not anything of a nix user, but.. where is ./utilization.txt supposed to be? The rest I understand, just not that bit. – Tetsujin Feb 22 at 15:32
  • 1
    ./ refers to current directory, the same way as ~/ refers to home. I'm running the command on directory "Desktop" I want to make sure the file does get created on my desktop, so I refer to it as ./utilization.txt. If I wanted it to be created in my home directory, regardless on what's my current directory, I'd refer to it as ~/utilization.txt. – Peregrino69 Feb 22 at 16:07
  • 1
    To check I just now tried the same command without the ./ -reference, so just "top | grep idle | tee utilization.txt". Same result, so the reference isn't throwing MacOS off. The failing part really appears to be the redirection itself. – Peregrino69 Feb 22 at 16:12
3

If STDOUT is redirected to a non-terminal (e.g. a file) a default buffer size of 4096 Byte is used. In the Terminal STDOUT defaults to line buffering.

Executing the command top | grep idle | tee >> ... will fill the 4k buffer with ~45-50 Byte/s (depending on load and sys|usr|idle split). After a while the first buffer will be written to file. Here, it took ~85 seconds to write the first buffer to the file system.


So either be patient 😴 or if you want the file to be updated immediately (i.e. every second), modify grep buffering:

top | grep idle --line-buffered | tee >> ./utilization.txt

Result after a few seconds:

$ cat ./utilization.txt 
CPU usage: 9.5% user, 11.49% sys, 79.44% idle 
CPU usage: 5.24% user, 10.48% sys, 84.26% idle 
CPU usage: 2.86% user, 4.74% sys, 92.39% idle 
CPU usage: 2.3% user, 1.91% sys, 96.5% idle 
CPU usage: 3.79% user, 2.25% sys, 93.95% idle 
CPU usage: 2.3% user, 3.35% sys, 94.61% idle 
CPU usage: 1.91% user, 1.91% sys, 96.16% idle 
CPU usage: 2.15% user, 2.51% sys, 95.33% idle 
CPU usage: 2.50% user, 4.29% sys, 93.20% idle 
CPU usage: 1.43% user, 1.7% sys, 97.48% idle 

If Terminal output is also required use: top | grep idle --line-buffered | tee ./utilization.txt saves the output to file and the result is visible in the Terminal window!

  • Thank you, @klanomath, that does the trick :-) Might you be able to explain why the --line-buffered -option is required here as I've never had to resort to it with other OS:s? – Peregrino69 Feb 22 at 18:02
  • As I don't really need the output on the terminal I tested whether this also works with >> -redirection. It indeed does :-) – Peregrino69 Feb 22 at 18:05
  • Thanks again, clear now :-) – Peregrino69 Feb 22 at 18:32
2

You need to produce one sample of top`s output.

top -l1 | grep idle | tee ./utilization.txt
  • That's not really very useful if your aim is to monitor CPU utilization over a period of time wouldn't you agree? :-) Without scripting a loop, that is. – Peregrino69 Feb 22 at 18:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .