skip to Main Content

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.

3

Answers


  1. 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
    
    Login or Signup to reply.
  2. 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%stName:t%stState:t%sn", 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%stName:t%stState:t%sn", 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
    
    Login or Signup to reply.
  3. 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
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search