George
George

Reputation: 29

How to read only certain (desired) data from more proc/[pid]/status

Lets say I want to extract current State (D/R/S/T/Z) and command Name from processes with given PID.

For example I have this code:

pids=$(pidof firefox) #returns all PID-s of firefox processes (random example)

for v in ${pids[*]}
    do
    echo "PID: $v" #here I also want to write status and name of the command (PID, Name, Status)
    done
more /proc/$$/status

returns

Name: bash
Umask: 002
State: S (sleeping)
....
Pid: 3234
...

From all that information I only need some. I want to know how to extract desired property (Name, Status,...) from proc.

Upvotes: 0

Views: 266

Answers (3)

j_b
j_b

Reputation: 2020

Using /proc/{pid1, pid2}/status and grep:

pids=$(pidof firefox); pids=${pids// /,}; grep '^Pid\|Name\|State' < <(bash <<<"cat /proc/{$pids}/status"

Sample output:

Name:   Isolated Servic
State:  S (sleeping)
Pid:    1052298
Name:   Isolated Web Co
State:  S (sleeping)
Pid:    981127

Upvotes: 1

Paul Hodges
Paul Hodges

Reputation: 15358

To avoid repeated calls to awk in the possibility that you have a lot of elements (unlikely, but hey, maybe it's a server of something...), but mostly as an exercise...

$: awk '/^Pid:/{ pid[FILENAME]=$2 } /^Name:/{ name[FILENAME]=$2 } /^State:/{ state[FILENAME]=$2 } END{ for (k in pid) printf "PID:\t%s\tName:\t%s\tState:\t%s\n", pid[k],name[k],state[k] }' $( sed -E 's,(.*),/proc/\1/status,' <(pidof firefox) ) 
PID:    1619    Name:   firefox State:  S
PID:    1620    Name:   firefox State:  S

One-liners are ugly - breaking it out -
(I don't actually have pidof or firefox on this laptop, so for full transparency I made a file with a couple pids and used cat lst instead of pidof firefox, so will just use that below.)

$: cat lst # the file
1619
1620
$: sed -E 's,(.*),/proc/\1/status,' <(cat lst) # the status inputs
/proc/1619/status
/proc/1620/status
$: awk '/^Pid:/{ pid[FILENAME]=$2 }
        /^Name:/{ name[FILENAME]=$2 }
        /^State:/{ state[FILENAME]=$2 }
        END{ for (k in pid) printf "PID:\t%s\tName:\t%s\tState:\t%s\n", pid[k],name[k],state[k] }
   ' $( sed -E 's,(.*),/proc/\1/status,' <(cat lst) )
PID:    1619    Name:   mintty  State:  S
PID:    1620    Name:   bash    State:  S

Upvotes: 0

markp-fuso
markp-fuso

Reputation: 34808

Using awk to pull out the Name and State:

$ awk '$1=="Name:"{name=$2;next}$1=="State:"{print name,$2;exit}' /proc/$$/status
bash S

Fixing issues with OP's code and pulling the awk script into the mix:

pids=( $(pidof firefox) #returns all PID-s of firefox processes (random example) )

for v in "${pids[*]}"
do
    read -r name state < <(awk '$1=="Name:"{name=$2;next}$1=="State:"{print name,$2;exit}' /proc/${v}/status)
    echo "PID: ${v} / Name: ${name} / State: ${state}"
done

Running against OP's single example this should generate:

PID: 3234 / Name: bash / State: S

Upvotes: 0

Related Questions