awk newbie here..
I’m trying this:
top -b -p 30259 | awk 'BEGIN { OFS = ","; print "Timestamp,CPU,Memory"} /tomcat/ { print strftime("%H:%M:%S"), $9, $10 }' > asdf.log
But ‘asdf.log’ always stays empty. I tried redirecting to file from within the script:
top -b -p 30259 | awk 'BEGIN { OFS = ","; print "Timestamp,CPU,Memory" > "asdf.log"} /tomcat/ { print strftime("%H:%M:%S"), $9, $10 > "asdf.log" }'
but it still doesn’t work… And printing to stdout is working fine.
What am I doing wrong?
How long are you waiting for data to arrive?
When programs use the standard C library to write to files (
fopen(3)and family of functions), the C library will add some buffering to the streams to improve performance. If every read or write of one character actually started a system call, the performance of common programs would be pretty horrible. So the C standard input routines will submit blocks of IO when the buffers are “full enough”.The tricky parts comes that the C standard IO routines will change their definition of “full enough” based on the specific file descriptors — if the file descriptor is to a file, then the IO is block buffered, and you must wait for a certain amount of data to arrive. (Check
stat asdf.log‘sIO Blockentry to see the most likely size.) However, if the file descriptor is forstdoutand it refers to a terminal device, the output is line buffered — output will be sent to the terminal as soon as a newline character is printed.Perhaps the
setvbuf(3)manpage can explain better than I can:Amend your script to look like this:
The
fflush()forces output immediately. Not great for performance, but better for viewing the state of your system in real time.