5

I am using this command below and trying to separate the columns I only want to get the PID to use it in my python script.

I can easily get this line by line but then how to separate into columns in a non hacky way?

I can easily split by space but lets face it that is a terrible idea, any suggestions?

root@python-VirtualBox:/var/python# lsof | grep TCP
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    3449 root    3u  IPv4  24248      0t0  TCP *:22 (LISTEN)
sshd    3449 root    4u  IPv6  24257      0t0  TCP *:22 (LISTEN)

5 Answers 5

10

The lsof command is quite full-featured, allowing you to specify many different search criteria. In particular, the -i option lets you search by Internet address, including protocol, rendering grep unnecessary. So you could replace

lsof | grep TCP

with

lsof -i TCP

lsof also allows you to specify which fields you are interested in with the -F option and only output those (one on each line). So we can do

lsof -i TCP -F 'p'

to output a list of PIDs for processes which are using TCP.

However, each of these PIDs is prefixed with a "p" (e.g. "p156"), so finally we can use cut to just get the numerical ID. This gives us a final command of

lsof -i TCP -F 'p' | cut -c 2-

Of course @RobertL's answer is also perfectly fine, but I like to challenge myself to not use AWK to solve all my text-processing challenges.

3

I think awk is good for this because it splits fields for you:

lsof | awk '$8 == "TCP" { print $2 }'

If field 8 is "TCP", then print field 2.

2
  • 1
    See also freebsd.org/cgi/…
    – Jeff Schaller
    Jan 16, 2016 at 19:02
  • 3
    …unless some column is empty, because awk cannot detect that, and will shift the remaining columns left :/ Dec 31, 2019 at 11:52
3

in:

lsof -iTCP -Fp

out:

p1135                                
p6326                                                                  
p16841                                                                 
p18130                                                                 
p37908                                                                 
p41768                                                                 
p51944                                                                 
p71882                                                                 
p74759                                                                 
p79636                                                                 
p82203                                
2
  • 2
    Why vote this down? It's correct, and provides all results, unlike lsof |grep TCP.
    – voices
    Jan 22, 2016 at 18:07
  • 3
    Probably because the same answer was already given with more details and a command to strip the 'p' prefix just hours before your answered. I gave you an upvote to compensate, because brevity is also a virtue :)
    – DylanYoung
    Oct 19, 2018 at 14:33
1

There is an option (-t) to list only PIDs. Combined with the -i option to filter TCP, it should do what you wanted (and no need to remove the 'p' prefix from the -F option):

lsof -i TCP -t

Output:

1
651
652
728
942
947
958
959
[...]

Version:

lsof -v
lsof version information:
    revision: 4.93.2
[...]
1
  • This should be the accepted answer.
    – Tommiie
    yesterday
1

The only truly safe option is to use e.g. lsof -F0pn and then parse the output with some other programming language. In that case, lsof will emit fields separated by null bytes and every field starts with a character that specifies the type of the field. For example p123<NULL>n/var/log/syslog<NULL> would mean that PID 123 has open file name called /var/log/syslog. Note that if the process has multiple files open, the p (PID) field will be listed only once and multiple n (name) fields will appear describing the files.

Also note that even if you request fields p and n with the -F flag, lsof may emit additional fields, too, so be prepared to be ignore the fields you're not interested in.

The lsof is part of POSIX spec and it has this weird behavior due historical reasons: https://www.unix.com/man-page/posix/8/lsof/

2
  • Why is this the only "truly safe" option? Why are the other answers not "safe" (enough)?
    – Tommiie
    yesterday
  • 1
    The answers that respond to literal question (that is use text processing to separate the columns) cannot work without using the -F flag because there are no real columns in lsof output. In addition, without the flag 0 for the -F, embedded linefeeds in command name or in the filename of lsof output will cause incorrect interpreation of the data. If you don't answer the original text processing question but only list the PIDs, then lsof -i TCP -t is definitely okay. yesterday

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .