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

Time:11-28

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.

CodePudding user response:

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

CodePudding user response:

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
  • Related