LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 10-16-2010, 10:39 AM   #16
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556

Yes the network numbers work correctly in both the AWK version and the sh version, as they are written for my system, but I believe where you had modified your script to only put one Dzen2, and thus taken the networking code from my second Dzen2 (which is actually displayed first and whose code is before the sleep) and placed it onto your single (Dzen2 which is printed after the sleep) the piece of code that saves the networking figures was in the wrong spot, and the difference was not being properly calculated.

As for the memory calculation, you may be right - the reading is sort of accurate, but is maybe not what one would expect to see for their mem usage. I guess it's because of the buffers & cache, and I don't fully understand the role of these items when looking at "real" free vs used memory.

When I first power up, my mem usage is near zero. But I made another thread somewhere in which I was asking about leaking memory, and why it is that after a few days of uptime my memory bar shows like 80%+ of my ram gone too, even with no apps running. I wanted a way to clear out the junk. The result is this:
Code:
cat /etc/sysctl.conf
# <--snip-->
vm.vfs_cache_pressure=50
vm.drop_caches=3
# <--snip-->
With that set up (mainly the drop_caches setting), I do the following command (now I do it in a cron job once per day in the morning):
Code:
sysctl -p
If I do that the cache gets cleaned and memory usage bar goes down instantly to like 10-20%.

I will have a look at the code for Mem usage and consider changing it to better reflect what `free` reports as you suggest. Also I am still tuning the awk version in other ways, so there will be another update of it later or tomorrow or so. I don't expect to work on the sh version much more, but if you use it and need any help on it, I'll be happy to help.

Best regards
 
Old 10-16-2010, 11:24 AM   #17
sycamorex
LQ Veteran
 
Registered: Nov 2005
Location: London
Distribution: Slackware64-current
Posts: 5,836

Original Poster
Blog Entries: 1

Rep: Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251
Quote:
Yes the network numbers work correctly in both the AWK version and the sh version, as they are written for my system, but I believe where you had modified your script to only put one Dzen2, and thus taken the networking code from my second Dzen2 (which is actually displayed first and whose code is before the sleep) and placed it onto your single (Dzen2 which is printed after the sleep) the piece of code that saves the networking figures was in the wrong spot, and the difference was not being properly calculated.
Ok, I'll have to look into the matter because I did not really think much about it. As you said earlier, dzen2 syntax is confusing. On top of that, I don't know awk. I think it's a good opportunity for me to get down and finally learn some awk.

I don't know much about linux memory handling but from what I understand linux caches a lot, which is beneficial to a system. My box has been up for a few days so there has been a lot of caching. Looking at the output of free,

Code:
             total       used       free     shared    buffers     cached
Mem:          5962       5459        503          0        530       4142
-/+ buffers/cache:        785       5176
Swap:         5999          0       5999
It would suggest that I've only got 503MB of free memory, which is not really accurate as the rest of memory is not being used by any other application. It's been cached (which I assume is good in terms of performance). However, the cached memory is not really taken because it can be freed in a split of a second if a program needs it. Therefore, my understanding is that my system's free memory is actually 5176 not 503MB. Again, I only vaguely understand it, but is there any point in clearing the cache?

thanks
 
Old 10-16-2010, 12:00 PM   #18
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
revision / modifications

OK, I think you're right about the memory. If you're wrong, I'll be wrong with you.

I've changed the get_mem() function so that:
USEDMEM = (TOTALMEM - FREEMEM - BUFMEM - CACHEMEM)

and the display looks good. I disabled my cache-cleaning cron for now so will see how this pans out over the next few days.

Also, I moved all the extra crap out of the while(1) loop and into its respective functions, and removed redundant code; now the loop simply sleeps & then executes the two print statements. This is much cleaner. I'm going to paste the new version here, and leave the last version in that post above so as to not cause confusion, and so they can be compared.

Also, a note worth mentioning:
In the sleep command inside the while(1) loop, you may notice I'm sleeping for .99 or .98 seconds. Why? To try to roughly account for the time it takes to actually one loop of the program:
Theoretically, (one loop incl. one sleep)=(one second), and that makes for proper calculating of CPU and network traffic over time, so I sleep for just under a second so the end result is a total execution time of one second per loop. Depending on machine speed, this value may be slightly off.

Oct 16 2010.. UPDATED VERSION:
Code:
#!/bin/awk -f

function get_date()
{
        DATE_CMD | getline STROUT; close(DATE_CMD)
        STROUT = "^fg("TX2")"STROUT
        return STROUT
}

function get_mem()
{
        check = 0
        while ((getline < MEMINFO) > 0) {
                if ($1 ~ /^MemTotal:/){ TOTALMEM = $2 ; check += 1; continue }
                if ($1 ~ /^MemFree:/) { FREEMEM  = $2 ; check += 1; continue }
                if ($1 ~ /^Buffers:/) { FREEMEM += $2 ; check += 1; continue }
                if ($1 ~ /^Cached:/)  { FREEMEM += $2 ; check += 1 }
                if (check == 4) { break }
        }
        close(MEMINFO)
        USEDMEM = (TOTALMEM - FREEMEM)
        UBARS   = int(USEDMEM * 100 / TOTALMEM)
        FBARS   = int(FREEMEM * 100 / TOTALMEM)
        if (UBARS >= 95) { FGCOL = "^fg("RED")" } else { FGCOL = "^fg("GRN")" }
        STROUT = "^fg(white)MEM:^p(2;4)"FGCOL"^r("UBARS"x16)^fg("BAR")^r("FBARS"x16)"
        return STROUT
}

function cpu_usage()
{
        # Calculate the CPU usage since we last checked.
        check = 0; TOTALCPU0 = 0; TOTALCPU1 = 0
        while ((getline < STAT) > 0) {
                if ($0 ~ /^cpu0 /) {
                        check += 1; IDLECPU0 = $5; for (x=2; x<=NF; x++) { TOTALCPU0 += $x; continue }
                }
                if ($0 ~ /^cpu1 /) {
                        check += 1; IDLECPU1 = $5; for (x=2; x<=NF; x++) { TOTALCPU1 += $x }
                }
                if (check == 2) { break }
        }
        close(STAT)
        DIFF_IDLE0 = IDLECPU0 - LASTIDLECPU0
        DIFF_IDLE1 = IDLECPU1 - LASTIDLECPU1
        DIFF_TOTAL0 = TOTALCPU0 - LASTTOTALCPU0
        DIFF_TOTAL1 = TOTALCPU1 - LASTTOTALCPU1
        DIFF_USAGE0 = int((100 * (DIFF_TOTAL0 - DIFF_IDLE0)) / DIFF_TOTAL0)
        DIFF_USAGE1 = int((100 * (DIFF_TOTAL1 - DIFF_IDLE1)) / DIFF_TOTAL1)
        if (DIFF_USAGE0 >= 95) { FG="^fg("RED")" } else { FG="^fg("GRN")" }
        STROUT = "^fg(white)CPU:^p(2;4)"FG"^r("DIFF_USAGE0"x8)^fg("BAR")^r("100-DIFF_USAGE0"x8)"
        if (DIFF_USAGE1 >= 95) { FG="^fg("RED")" } else { FG="^fg("GRN")" }
        STROUT = STROUT"^p(-100;8)"FG"^r("DIFF_USAGE1"x8)^fg("BAR")^r("100-DIFF_USAGE1"x8)"
        LASTTOTALCPU0 = TOTALCPU0; LASTIDLECPU0 = IDLECPU0
        LASTTOTALCPU1 = TOTALCPU1; LASTIDLECPU1 = IDLECPU1
        return STROUT
}

function disk_space()
{
        STROUT = ""
        while ((DF_CMD | getline) > 0) {
                if ($6 !~ /Mounted|\/dev\/shm/) {
                        DEVUSED = $2 - $4
                        UBARS = int(DEVUSED * 100 / $2)
                        FBARS = int($4 * 100 / $2)
                        if (UBARS >= 95) { FGCOL = "^fg("RED")" } else { FGCOL = "^fg("GRN")" }
                        STROUT = STROUT"^pa(;0)^fg(white)"$6":^p(2;4)"FGCOL"^r("UBARS"x16)^fg("BAR")^r("FBARS"x16) "
                }
        }
        close(DF_CMD)
        return STROUT
}

function interfaces()
{
        STROUT = ""
        while ((IPGLOBAL_CMD | getline) > 0) {
                if ($0 ~ /^[ ]*inet /) {
                        LOC = "/sys/class/net/"$NF"/statistics/rx_bytes"
                        getline RXBN[$NF] < LOC; close(LOC)
                        LOC = "/sys/class/net/"$NF"/statistics/tx_bytes"
                        getline TXBN[$NF] < LOC; close(LOC)
                        RXR[$NF] = int((RXBN[$NF] - RXB[$NF]) / 1024); RXB[$NF] = RXBN[$NF]
                        TXR[$NF] = int((TXBN[$NF] - TXB[$NF]) / 1024); TXB[$NF] = TXBN[$NF]
                        STROUT = STROUT "^fg(white)"$NF"^fg("BAR") "TXR[$NF]"^fg("GRY")^p(2)UkB/s ^fg("BAR")"RXR[$NF]"^fg("GRY")^p(2)DkB/s"
                        IPLABEL_CMD  = "/sbin/ip addr show label "$NF; IPADDR = ""
                        while ((IPLABEL_CMD | getline) > 0) {
                                if ($0 ~ /inet /) { gsub("/.*","",$2); IPADDR = $2; break }
                        }
                        close(IPLABEL_CMD)
                        STROUT = STROUT" ^fg("BAR")"IPADDR
                }
        }
        close(IPGLOBAL_CMD)
        return STROUT
}

function workspaces(display)
{
        RS = "},{"; FS = ","; XPOS = 1681; STROUT = ""
        while ((I3SOCK_CMD | getline) > 0) {
                NEEDCOLOR = 1
                if ($NF ~ /true/) {             TAGCOLOR = "#FF5555"; TEXTCOLOR = "#FFFFFF"; NEEDCOLOR = 0 }
                if (NEEDCOLOR && $3 ~ /true/) { TAGCOLOR = "#FFFFFF"; TEXTCOLOR = "#000000"; NEEDCOLOR = 0 }
                if (NEEDCOLOR) {                TAGCOLOR = "#A0A0A0"; TEXTCOLOR = "#000000" }
                gsub(/"|\[|\]|{|}/,"")
                split($2, ONAME, ":")
                split($(NF-1), OUTPUT, ":")
                if (OUTPUT[2] == display && display == "xinerama-0") {
                        STROUT = STROUT"^fg("TAGCOLOR")^r(30x22)^p(-21)^fg("TEXTCOLOR")"ONAME[2]"^p(+11)"; XPOS -= 32; continue
                }
                if (OUTPUT[2] == display && display == "xinerama-1") {
                        STROUT = STROUT"^fg("TAGCOLOR")^r(30x22)^p(-21)^fg("TEXTCOLOR")"ONAME[2]"^p(+11)"; XPOS = 1
                }
        }
        close(I3SOCK_CMD)
        STROUT = "^pa("XPOS";1)"STROUT
        RS = "\n"; FS = " "
        return STROUT
}

function show_help ()
{
        print
        print "This script is called \"dzen2-wrapper\""
        print "This is a wrapper/startup script for feeding various information"
        print "into one or more Dzen2 status bars. To start it from your WM or"
        print "from xinitrc or from CLI, I suggest a command like:"
        print "`/path/to/dzen2-wrapper [option] & disown`"
        print "This script accepts one of three options: stop, nostop, and help;"
        print "stop:   stop all dzen2's and wrapper scripts, and exit."
        print "nostop: start new instance without stopping any other instances."
        print "help:   show this help info you're reading now."
        print
        print "License: GPLv3 or greater. Warranty: none."
        print "Author:  GrapefruiTgirl"
        print "Thanks:  Members of the linuxquestions.org community."
        print
}

BEGIN{
if (ARGV[1] ~ /help|-h/) { show_help(); exit 0 }

if ("nostop" !=  ARGV[1]) {
# Yes, this killing code is not good. I could be less delicate/more brutal
# but for now, it is what it is. Note: "nostop" option passed to the script
# can be handy if you want to run a second+ X session somewhere and want
# dzen2's there as well as on your initial session.
        RS="\n"; FS = " "; count = 0
        PS_CMD1 = "ps --no-headers -C dzen2 2>/dev/null"
        PS_CMD2 = "ps --no-headers -C dzen2 >/dev/null 2>&1"
# NOTE: Next line must have the filename of this as the argument to -C
        PS_CMD3 = "ps --no-headers -C dzen2-wrapper 2>/dev/null"
        while ((PS_CMD3 | getline) >0) {
                if ($1 != PROCINFO["pid"]) { system("kill -9 "$1" >/dev/null 2>&1") }
        }
        close(PS_CMD3)
        while (system(PS_CMD2) == 0) {
                while ((PS_CMD1 | getline) >0) {
                        system("kill -9 "$1" 2>/dev/null")
                }
                close(PS_CMD1)
                count += 1; system("/bin/sleep 1")
                if (count >=5) {
                        print "dzen2-wrapper error: unkillable zombie dzen2's." > "/dev/stderr"; exit 1
                }
        }
        close(PS_CMD2)
}

# See if we're being told to stop all Dzen2's and not restart:
if ("stop" == ARGV[1]) { exit 0 }

# VARIABLES: Define colors and things:
TX1="#DBDADA"                           # medium grey text
TX2="#F9F9F9"                           # light grey text
GRY="#909090"                           # dark grey text
BAR="#A6F09D"                           # green background of bar-graphs
GRN="#65A765"                           # light green (normal)
RED="#FF0000"                           # light red/pink (warning)
LASTTOTALCPU0 = 0; LASTIDLECPU0 = 0     # zero some vars for \
LASTTOTALCPU1 = 0; LASTIDLECPU1 = 0     # ..the CPU load reader
delete ARGV                             # we don't need ARGV anymore.

# COMMANDS & /proc files for use w/getline:
DATE_CMD     = "date +'%H:%M:%S %a %x'"
DF_CMD       = "df"
IPGLOBAL_CMD = "/sbin/ip addr show scope global"
I3SOCK_CMD   = "i3-msg -s /tmp/i3-ipc.sock -t get_workspaces"
MEMINFO      = "/proc/meminfo"
STAT         = "/proc/stat"

while (1) {
        system("/bin/sleep .98")

print "^ib(1)^pa(0;0)^fg("BAR")^ro(1680x24)^pa(2;0)"get_date()"^pa(;0) "get_mem()"^pa(;0) "cpu_usage()"^pa(;0) "disk_space()" "workspaces("xinerama-0") |\
 "dzen2 -fn -bitstream-terminal-bold-r-normal--20-140-100-100-c-110-iso8859-1 -bg black -ta l -h 24 -u -p -xs 1 -dock -e 'sigusr1=exit'"

print "^ib(1)^pa(0;0)^fg("BAR")^ro(1680x24)^pa(0;0)"workspaces("xinerama-1")"^pa(;0) "interfaces() |\
 "dzen2 -fn -bitstream-terminal-bold-r-normal--20-140-100-100-c-110-iso8859-1 -bg black -ta l -h 24 -u -p -xs 2 -dock -e 'sigusr1=exit'"

} # end of while(1)

} # end of BEGIN

END{}

Last edited by GrapefruiTgirl; 10-16-2010 at 08:48 PM. Reason: Found logic error in memory calculation. Fixed.
 
Old 10-23-2010, 02:35 PM   #19
sycamorex
LQ Veteran
 
Registered: Nov 2005
Location: London
Distribution: Slackware64-current
Posts: 5,836

Original Poster
Blog Entries: 1

Rep: Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251Reputation: 1251
Thanks for an updated version of the script. It seems to work fine for me (after some tailoring).

I have now exclusively been using i3 for 2 weeks. It seems that it's here to stay

cheers
sycamorex
 
Old 10-23-2010, 03:10 PM   #20
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556Reputation: 556
Sounds good!

Perhaps at some point you will post your script, as a "single monitor" version, while I will post mine as the "dual monitor" version -- then there's less potential tailoring to be done by anyone who wants to use either version on their own system..

I think I have fine-tuned mine a little more again, since the last upgraded paste I did above, but the changes were very minor so I may not have pasted it again since. One thing I do remember doing, was changing to AWK's built-in `strtoftime` function to produce the date string, rather than making the (external) call to /bin/date.

I'll update again eventually (perhaps once I finish this other little project I've just started!) but I'm sure you're doing OK for now, with the current version.

Continued fun!
Cheers,
Sasha
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Ubuntu Status Bar cmnorton Ubuntu 2 12-17-2009 10:22 AM
Recover status bar devmohan786 Linux - Software 2 07-22-2008 02:48 PM
[SOLVED] lost task bar and status bar how to get them back devmohan786 Linux - Software 2 07-13-2008 04:00 AM
Remove Konqueror Status Bar Ace2005 Linux - General 2 10-10-2005 11:37 AM
System status bar? mikegorb Linux - Software 4 12-13-2004 10:46 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 04:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration