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)
I am interested in the PID
column for user-x
. So what I want is 2670
and 2756
.
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.
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.
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.
Thanks to @jhnc's comment, I found that pkill -u user-x
worked well and avoids this whole issue. Leaving the question as-is though, since @markp-fuso's answer actually does provide a solution to what was asked.
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}'