How can I get the PID column from the output of `who -u`?

Background
Calling who -Hu
on my machine gives this result:
$ who -Hu
NAME LINE TIME IDLE PID COMMENT
rpi-first-boot-wizard tty7 1970-01-10 11:44 02:31 1204 (:0)
user-x tty2 1970-01-07 20:16 00:10 2670
user-x pts/0 4164607823021491175 . 2756 (192.168.203.57)
Problem
I am interested in the PID
column for user-x
. So what I want is 2670
and 2756
.
What I tried
I looked through the man pages of who
, but there are no options to get a specific column or to suppress certain columns.
I tried with who -u | grep user-x | tr -s ' ' | cut -d ' ' -f 5
, but that only works for the row(s) that have the timestamp as a single number with no spaces. For some reason, some of the lines have a timestamp that includes spaces, so it's hard to parse.
What I want
It would be nice to have some simple bash command(s) that I could use to get the PIDs from the output. I'm just not sure exactly how to manipulate the strings correctly. I would rather not have to use a programming language to parse this output, but if I can't find out a nice way to do it with bash, then that's what I will have to end up doing.
Other info
In case this is an "XY problem," what I am really trying to do is kick a specific user out of my system, so I plan to pass these PIDs into kill
, like who -u | grep user-x | tr -s ' ' | cut -d ' ' -f 5 | xargs kill
. This worked like a charm until I started encountering sessions that use this wonky date format with the spaces. If there is another way to get the right PIDs that does not include using who
, then that would also suffice.
Answer
Assuming you want to capture the PIDs for some other reason besides issuing a kill
(eg, appending to a log file) ...
Using the following file to simulate OP's who -Hu
call:
$ cat who.out
NAME LINE TIME IDLE PID COMMENT
rpi-first-boot-wizard tty7 1970-01-10 11:44 02:31 1204 (:0)
user-x tty2 1970-01-07 20:16 00:10 2670
user-x pts/0 4164607823021491175 . 2756 (192.168.203.57)
One approach using awk
:
cat who.out | awk -v user="user-x" '
$1==user { gsub(/\([^)]+\)/,"") # strip off the parenthesized string at end of line
print $1, $NF # print 1st and last fields
}
'
########
# or as a one-liner:
cat who.out | awk -v user='user-x' '$1==user { gsub(/\([^)]+\)/,"") ; print $1, $NF}'
These both generate:
user-x 2670
user-x 2756
If you only need the PIDs in the output then change print $1, $NF
to print $NF
.
In OP's case the call would look like:
who -Hu | awk -v user='user-x' '$1==user { gsub(/\([^)]+\)/,"") ; print $1, $NF}'
Enjoyed this question?
Check out more content on our blog or follow us on social media.
Browse more questions