• Get name and swap from status file

    From Cecil Westerhof@21:1/5 to All on Mon Feb 21 00:48:05 2022
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    I want to extract the name and the kB's of swap.

    For this I use something like:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}
    set statusF [open /proc/1002/status]
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]

    Is that a good idea, or could I better implement it in a different
    way?

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to Cecil Westerhof on Mon Feb 21 00:17:25 2022
    Cecil Westerhof <[email protected]> wrote:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    I want to extract the name and the kB's of swap.

    For this I use something like:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}
    set statusF [open /proc/1002/status]
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]

    Is that a good idea, or could I better implement it in a different
    way?

    That's one way, but not the only way. Another way is something like
    this:

    proc procget {file} {
    set fd [open $file RDONLY]

    while {[gets $fd line] != -1} {
    switch -regexp -matchvar mv -- $line {
    {^Name:[[:blank:]]+([^\n]+)} { set name [lindex $mv 1] }
    {^VmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB} {
    set swap [lindex $mv 1]
    close $fd
    return [list $name $swap]
    }
    }
    }
    close $fd
    error "Did not find expected data"
    }

    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rich@21:1/5 to jtyler on Mon Feb 21 06:15:14 2022
    jtyler <[email protected]> wrote:
    On 2/20/2022 4:17 PM, Rich wrote:

    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.


    If better means easiest, then this comes to mind:


    $ rlwrap -pred tclsh
    % set line {}
    % catch {set line [exec grep -s VmSwap /proc/1351/status]}
    0
    % set line
    VmSwap: 44852 kB
    % lindex $line 1

    This does rely on the contents of the status file in proc not being
    someday modified to include a character that is special to the Tcl
    implicit string to list parsing code.

    Relying on implicit string to list conversion is a source of weird
    errors, years later, at 3:17am, while you are away for a vacation, that
    is dependent on the fact that at that exact time, a "special character"
    (to the string to list parsing code) appeared in the data being
    consumed.

    I.e., it is an "input data dependent bug".

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jtyler@21:1/5 to Rich on Sun Feb 20 21:38:23 2022
    On 2/20/2022 4:17 PM, Rich wrote:

    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.


    If better means easiest, then this comes to mind:


    $ rlwrap -pred tclsh
    % set line {}
    % catch {set line [exec grep -s VmSwap /proc/1351/status]}
    0
    % set line
    VmSwap: 44852 kB
    % lindex $line 1
    44852
    % set line {}
    % catch {set line [exec grep -s VmSwap /proc/1351noexist/status]}
    1
    % set line
    %

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From heinrichmartin@21:1/5 to Rich on Mon Feb 21 00:04:05 2022
    On Monday, February 21, 2022 at 1:17:30 AM UTC+1, Rich wrote:
    Cecil Westerhof wrote:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    I want to extract the name and the kB's of swap.

    For this I use something like:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}
    set statusF [open /proc/1002/status]
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]
    [...]
    [...]
    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.

    A few suggestions (beyond RDONLY that Rich suggested):
    * there is [fileutil::cat]
    * you have not stated which process - /proc/[pid]/status ?
    * there is [string cat] instead of multiple [append]s
    * depending on future plans, you might want to parse the key-value-pairs to a dictionary ...

    # this is my take from the console - maintainable code looks different ;-) package require fileutil
    set status [concat {*}[lmap line [split [::fileutil::cat /proc/[pid]/status] \n] {
    if {[regexp {^([^:]+):\s+(.*)$} $line -> name value]} {list $name $value} continue
    }]]
    puts [dict get $status VmSwap] ;# still with the unit attached

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cecil Westerhof@21:1/5 to Rich on Mon Feb 21 09:57:46 2022
    Rich <[email protected]d> writes:

    Cecil Westerhof <[email protected]> wrote:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    I want to extract the name and the kB's of swap.

    For this I use something like:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n} >> set statusF [open /proc/1002/status]
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]

    Is that a good idea, or could I better implement it in a different
    way?

    That's one way, but not the only way. Another way is something like
    this:

    proc procget {file} {
    set fd [open $file RDONLY]

    while {[gets $fd line] != -1} {
    switch -regexp -matchvar mv -- $line {
    {^Name:[[:blank:]]+([^\n]+)} { set name [lindex $mv 1] }
    {^VmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB} {
    set swap [lindex $mv 1]
    close $fd
    return [list $name $swap]
    }
    }
    }
    close $fd
    error "Did not find expected data"
    }

    I had to look twice, but that works.


    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.

    For the moment I will keep with mine version. That is more of my
    taste. ;-)


    But when the input-file can become large, your way would probably be
    better.

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Uwe Klein@21:1/5 to All on Mon Feb 21 11:07:27 2022
    Am 21.02.22 um 00:48 schrieb Cecil Westerhof:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    Is that a good idea, or could I better implement it in a different
    way?

    Use the System, Luke!

    set swapinfo [ exec grep VmSwap: /proc/$PID/status ]


    you work in a known system ( linux : has grep .. )
    and it is obvious what the code wants to achieve.
    and kiss : one line.

    Uwe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cecil Westerhof@21:1/5 to heinrichmartin on Mon Feb 21 10:57:01 2022
    heinrichmartin <[email protected]> writes:

    On Monday, February 21, 2022 at 1:17:30 AM UTC+1, Rich wrote:
    Cecil Westerhof wrote:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    I want to extract the name and the kB's of swap.

    For this I use something like:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}
    set statusF [open /proc/1002/status]
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]
    [...]
    [...]
    There are also multiple other ways.

    As to which is /better/, I suspect that is going to be largely a matter
    of taste.

    A few suggestions (beyond RDONLY that Rich suggested):

    Yeah, I already added that. Is the default, but it makes things
    clearer.


    * there is [fileutil::cat]

    I will look into that.


    * you have not stated which process - /proc/[pid]/status ?

    It was hard-coded. But see end of the post.


    * there is [string cat] instead of multiple [append]s

    I look into that also.


    * depending on future plans, you might want to parse the
    key-value-pairs to a dictionary ...

    At the moment that looks like overkill.


    At the moment I have:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}


    foreach file [glob /proc/*/status] {
    try {
    set statusF [open $file RDONLY]
    } on error msg {
    # Process does not exist anymore
    if {${::errorCode} == {POSIX ENOENT {no such file or directory}}} {
    continue
    }
    puts "errorInfo: ${::errorInfo}"
    puts "errorCode: ${::errorCode}"
    puts "msg: ${msg}"
    exit
    }
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]
    if {${result} && ($swap != 0)} {
    puts "$name: $swap"
    }
    }

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cecil Westerhof@21:1/5 to Cecil Westerhof on Mon Feb 21 11:21:40 2022
    Cecil Westerhof <[email protected]> writes:

    * there is [fileutil::cat]

    I will look into that.

    [snip]

    * there is [string cat] instead of multiple [append]s

    I look into that also.



    [snip]

    At the moment I have:
    set regex {}
    append regex {^Name:[[:blank:]]+([^\n]+)\n}
    append regex {.*}
    append regex {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n}


    foreach file [glob /proc/*/status] {
    try {
    set statusF [open $file RDONLY]
    } on error msg {
    # Process does not exist anymore
    if {${::errorCode} == {POSIX ENOENT {no such file or directory}}} {
    continue
    }
    puts "errorInfo: ${::errorInfo}"
    puts "errorCode: ${::errorCode}"
    puts "msg: ${msg}"
    exit
    }
    set statusStr [read ${statusF}]
    close ${statusF}
    set result [regexp ${regex} ${statusStr} match name swap]
    if {${result} && ($swap != 0)} {
    puts "$name: $swap"
    }
    }

    Changed it to:
    package require fileutil


    set regex [string cat \
    {^Name:[[:blank:]]+([^\n]+)\n} \
    {.*} \
    {\nVmSwap:[[:blank:]]+([[:digit:]]+)[[:blank:]]+kB\n} \
    ]


    foreach file [glob /proc/*/status] {
    try {
    set statusStr [::fileutil::cat $file]
    } on error msg {
    # Process does not exist anymore
    if {${::errorCode} == {NONE}} {
    continue
    }
    puts "errorInfo: ${::errorInfo}"
    puts "errorCode: ${::errorCode}"
    puts "msg: ${msg}"
    exit
    }
    set result [regexp ${regex} ${statusStr} match name swap]
    if {${result} && ($swap != 0)} {
    puts "$name: $swap"
    }
    }

    When a file does not exist ::fileutil::cat generates the error NONE.
    Personally I find that a bit strange.

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Cecil Westerhof@21:1/5 to Uwe Klein on Mon Feb 21 12:49:19 2022
    Uwe Klein <[email protected]> writes:

    Am 21.02.22 um 00:48 schrieb Cecil Westerhof:
    In linux you find in /proc/PID/status:
    Name: exim4
    .
    .
    .
    VmSwap: 980 kB

    Is that a good idea, or could I better implement it in a different
    way?

    Use the System, Luke!

    set swapinfo [ exec grep VmSwap: /proc/$PID/status ]


    you work in a known system ( linux : has grep .. )
    and it is obvious what the code wants to achieve.
    and kiss : one line.

    But it does not what I want: retrieve exactly name and swap.
    And could also be relatively expensive.

    --
    Cecil Westerhof
    Senior Software Engineer
    LinkedIn: http://www.linkedin.com/in/cecilwesterhof

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Uwe Klein@21:1/5 to All on Mon Feb 21 17:18:57 2022
    Am 21.02.22 um 17:17 schrieb Uwe Klein:
    Am 21.02.22 um 12:49 schrieb Cecil Westerhof:
    set swapinfo [ exec grep VmSwap: /proc/$PID/status ]

    % set swapinfo [ exec egrep VmSwap:\|Name /proc/6239/status ]
    Name: lyx
    VmSwap: 45868 kB
    %

    a Billion ways to go from there :-)

    Uwe

    % time { set swapinfo [ exec egrep VmSwap:\|Name /proc/6239/status ]} 100 4527.38 microseconds per iteration
    %
    Uwe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Uwe Klein@21:1/5 to All on Mon Feb 21 17:17:25 2022
    Am 21.02.22 um 12:49 schrieb Cecil Westerhof:
    set swapinfo [ exec grep VmSwap: /proc/$PID/status ]

    % set swapinfo [ exec egrep VmSwap:\|Name /proc/6239/status ]
    Name: lyx
    VmSwap: 45868 kB
    %

    a Billion ways to go from there :-)

    Uwe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Mon Feb 21 18:54:34 2022
    * Uwe Klein <[email protected]>
    | % time { set swapinfo [ exec egrep VmSwap:\|Name /proc/6239/status ]} 100
    | 4527.38 microseconds per iteration

    % time { set swapinfo [ exec egrep VmSwap:\|Name /proc/3640/status ]} 100 2132.79 microseconds per iteration

    proc swapinfo {} {
    set res [list]
    set pid [pid]
    set fd [open /proc/$pid/status]
    while {[gets $fd line] >= 0} {
    if {[string range $line 0 4] eq "Name:"
    || [string range $line 0 6] eq "VmSwap:"} {
    lappend res $line
    if {[llength $res] == 2} {
    break
    }
    }
    }
    close $fd
    return $res
    }

    % time swapinfo 100
    59.26 microseconds per iteration

    :-)

    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Uwe Klein@21:1/5 to All on Mon Feb 21 22:58:12 2022
    Am 21.02.22 um 18:54 schrieb Ralf Fassel:
    * Uwe Klein <[email protected]>
    | % time { set swapinfo [ exec egrep VmSwap:\|Name /proc/6239/status ]} 100 | 4527.38 microseconds per iteration

    % time { set swapinfo [ exec egrep VmSwap:\|Name /proc/3640/status ]} 100 2132.79 microseconds per iteration

    different hardware

    proc swapinfo {} {
    set res [list]
    set pid [pid]
    set fd [open /proc/$pid/status]
    while {[gets $fd line] >= 0} {
    if {[string range $line 0 4] eq "Name:"
    || [string range $line 0 6] eq "VmSwap:"} {
    lappend res $line
    if {[llength $res] == 2} {
    break
    }
    }
    }
    close $fd
    return $res
    }

    % time swapinfo 100
    59.26 microseconds per iteration


    touche
    :-)

    R'

    G!
    Uwe

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Tue Feb 22 04:48:20 2022
    using an inline glob style search of a list of lines from the status file seems faster than swapinfo on my machine, and to my eye is easy to read and modify.


    proc getkv {file {key VmSwap:*}} {

    set fd [open $file r]
    try {
    set lines [split [read $fd] \n]
    } finally {close $fd}

    set name [lsearch -inline -glob $lines Name:*]
    if {"" eq $name} {
    error "no Name: line in $file"
    }

    set val [lsearch -inline -glob $lines $key]
    if {"" eq $val} {
    error "No $key line found in $file"
    }

    list [getval $name] [getval $val]
    }


    this trims any leading or trailing white space from whatever is after the first ":"

    proc getval {str} {
    string trim [string range $str [string first ":" $str]+1 end]
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)