Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Parseable format out of ps -commands (procps vs. busybox)
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3687
Location: Rasi, Finland

PostPosted: Wed Jul 19, 2023 8:46 am    Post subject: Parseable format out of ps -commands (procps vs. busybox) Reply with quote

I've started a new topic here as it thought it needed its own.
geki wrote:
I played a bit with my ps tools from busybox and procps-ng. I recommend to use args over comm to get the process command in full length. You can set the width of the columns of the output of ps by setting its header name. :o
Code:
$ busybox ps -Ao user=ThisIsmYLongUserHeader,pid,tty,args
and
Code:
$ ps -Ao user=ThisIsmYLongUserHeader,pid,tty,args
I'd use exe but busybox ps doesn't support it.
Your solution is almost perfect (although a bit hacky), but the tty column (which is important to me) differs. I could process the output and make it work. But here's the last thing I wish both ps command could do: seperate columns with tab.
It would be much easier to process. I know I love tsv format. :D

Meanwhile I've created this slow beast:
Code:
#!/bin/sh
find /proc -regex '^/proc/[0-9][0-9]*' 2> /dev/null | while read proc
do
    rp="$(realpath "${proc}/exe" 2> /dev/null)"
    if [ "$rp" != "${proc}/exe" ] && [ -e "${proc}/loginuid" ]
    then
        unset uid stdin
        # Reading the content of loginuid will give "wrong" uid sometimes
        uid="$(stat -c '%u'$'\t''%U' "${proc}/loginuid")"
        stdin="$(realpath "${proc}/fd/0" 2> /dev/null)"
        printf '%s\t%s\t%s\t%s\n' "${proc##*/}" "${uid}" "${stdin:-'N/A'}" "${rp}"
    fi
done
Crawling trough /proc is even worse hack, but I can get out neat tsv.
Also this is so slow (compared to each ps -command) that monitoring of processes is quite a heavy task. For one time listing, it's fine I guess.
_________________
..: Zucca :..

My gentoo installs:
init=/sbin/openrc-init
-systemd -logind -elogind seatd

Quote:
I am NaN! I am a man!
Back to top
View user's profile Send private message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3687
Location: Rasi, Finland

PostPosted: Wed Jul 19, 2023 6:29 pm    Post subject: Reply with quote

I managed make this "shell ps" quite faster with awk passing contents of proc to start via xargs.
And oh boy I once again stumbled into incompatibilities with few common tools.
Code:
#!/bin/sh

if [ "$1" != 'awk' ]
then
        find /proc -maxdepth 1 -mindepth 1 -regex '^/proc/[0-9][0-9]*' 2> /dev/null | while read proc
        do
            rp="$(realpath "${proc}/exe" 2> /dev/null)"
            if [ "$rp" != "${proc}/exe" ] && [ -e "${proc}/loginuid" ]
            then
                # The line below will give uid of the user who started the process,
                # not the user currently running it. Also root uid becomes 2^32-1.
                #read uid < "${proc}/loginuid"
                unset uid stdin
                # This line however will work as intended.
                uid="$(stat -c '%u'$'\t''%U' "${proc}/loginuid")"

                # A hacky way (?) to get the tty.
                # Really gets the tty where the process receives input (stdin).
                stdin="$(realpath "${proc}/fd/0" 2> /dev/null)"
                if [ "${stdin:$((${#str}-1)):1}" = ']' ]
                then
                        stdin="pipe:${stdin##*/pipe:}"
                fi
                printf '%s\t%s\t%s\t%s\n' "${proc##*/}" "${uid}" "${stdin:-'N/A'}" "${rp}"
            fi
        done
else
        # This may be possible to do with single awk...
        # We need to avoid find's -exec +, since findutils' find doesn't support -exec command "{}/foo".
        # Meaning {} needs to be "alone". Stangely enough busybox find supports this.
        # We call awk to run two separate 'xargs' which in turn run 'stat'.
        find /proc -maxdepth 1 -mindepth 1 -regex '^/proc/[0-9][0-9]*' \
                | awk -v tab=$'\t' '{print $0 "/exe" | "xargs stat -c \"%u" tab "%U" tab "%N\""; print $0 "/fd/0" | "xargs stat -c \"%N\""}' 2> /dev/null \
                | awk -v sg="'" -v FS=$'\t' -v OFS=$'\t' '
                        function parsepid(p) {
                                match(p,/\/[0-9]+\//)
                                return substr(p,RSTART+1,RLENGTH-2)
                        }

                        {
                                if (match($3,/-> .+$/)) {
                                        # Since busybox awk does not support nested arrays
                                        # we need to juggle around with several, one-dimensional, arrays
                                        S=RSTART
                                        L=RLENGTH
                                        pid=parsepid($3)
                                        procs[pid]=substr($3,S+4,L-5)
                                        uids[pid]=$1
                                        users[pid]=$2

                                } else if (match($1,/-> .+$/)) {
                                        S=RSTART
                                        L=RLENGTH
                                        ttys[parsepid($1)]=substr($1,S+4,L-5)
                                }
                        }

                        END {
                                for (pid in procs) {
                                        tty=ttys[pid]
                                        if (tty == "") tty = "N/A"
                                        print pid,uids[pid],users[pid],tty,procs[pid]
                                }
                        }
                '
fi
Passing "awk" as an argument uses the new, improved method. Compared to the older method this awk way doesn't spawn nearly as many sub processes to query the files inside /proc.

Finally. I have (somewhat) universal shell method to list processes? Right?
_________________
..: Zucca :..

My gentoo installs:
init=/sbin/openrc-init
-systemd -logind -elogind seatd

Quote:
I am NaN! I am a man!
Back to top
View user's profile Send private message
geki
Advocate
Advocate


Joined: 13 May 2004
Posts: 2387
Location: Germania

PostPosted: Thu Jul 20, 2023 8:22 pm    Post subject: Reply with quote

You can set for all columns but the args column a header-name. The length of the header-name is the width of the column. With that knowledge you can split the line to the respective entries. If you find a comma in the tty entry, you can map the major number to /dev/<device> like /dev/tty or /dev/pts by
Code:
$ busybox ps -Ao tty|grep -v "?"
...
136,0
136,0
136,0
$ grep "136 " /proc/devices
136 pts
$ ls /dev/pts/0
/dev/pts/0
That is as far as it gets with pses for now. :o I would keep processing /proc to a minimum. But that's me. :lol:

edit P.S.: This is just a basic example. grep should match with start of line (^). But how you parse /proc/devices properly is up to you and the systems targeted. Same for the comma test of tty entry. There you should also verify that the rest of the entry is only numbers.
edit #2
Hah. Its not that easy to parse /proc/devices. An exercise for the reader. :o
_________________
hear hear
Back to top
View user's profile Send private message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3687
Location: Rasi, Finland

PostPosted: Sat Jul 22, 2023 9:30 pm    Post subject: Reply with quote

Well. I tried playing around with the header name trick and ran:
Code:
ps -Ao user="$(printf %32s)",tty="$(printf %32s)",args
busybox accepts spaces as header name while procps does not.

I'm starting to question why am I even doing this? :D I guess I like challenges.
Next solution would be to pipe the printf generated string to tr " " "-" or so...
_________________
..: Zucca :..

My gentoo installs:
init=/sbin/openrc-init
-systemd -logind -elogind seatd

Quote:
I am NaN! I am a man!
Back to top
View user's profile Send private message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3687
Location: Rasi, Finland

PostPosted: Mon Sep 16, 2024 7:30 pm    Post subject: Reply with quote

So... oops? I made it into a small project.
https://codeberg.org/Zucca/procfsps

Available on my overlay too.
_________________
..: Zucca :..

My gentoo installs:
init=/sbin/openrc-init
-systemd -logind -elogind seatd

Quote:
I am NaN! I am a man!
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum