1

On Ubuntu, I often run some server/daemon and some clients both locally. The server/daemon and clients can be arbitrary programs (emacs daemon and clients, Screen daemon and clients, server and clients someone wrote), and suppose you don't how they are named.

  • Is there some way to find the PID of the server/daemon, given only the PID of a client process?

  • Is there some way to find the PIDs of all the clients, given only the PID of the server/daemon?

If what I am asking is impossible, what extra minimum information do you need to achieve the goals for as general purpose as possible?

Thanks.

  • 1
    If the applications are using sockets to communicate, you could see which sockets each PIDs are connected to and which PIDs are listening on the other end. netstat and lsof are your friends here. – multithr3at3d Dec 1 '18 at 1:54
  • Thanks. Can you give some example commands to achieve both goals? What are other ways to implement server clients besides using sockets to communicate? – Tim Dec 1 '18 at 1:55
  • @Tim this could be of interest -- but beware that both lsof and ss are pretty difficult, to use a mild word. – mosvy Dec 1 '18 at 3:42
  • @mosvy Thanks. "difficult" in what sense? – Tim Dec 4 '18 at 0:22
  • In the sense that I find their user interface pretty hugged up. If you're able to use either of them without having to look up each time the options in the the manual and/or write a script to make sense of the output -- great for you ;-) – mosvy Dec 4 '18 at 1:56
2

Most forms of IPC (inter-process communication) can be traced with a few utilities. Sockets (both network and UNIX sockets) are very commonly used and can be traced using some common tools. Let's look at an example using netstat -ap:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN      810/python3         
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      858/nginx: master process 
<snip>
tcp        0      0 127.0.0.1:46858         127.0.0.1:5000          ESTABLISHED 860/nginx: worker process
<snip> 
tcp        0      0 127.0.0.1:5000          127.0.0.1:46858         ESTABLISHED 810/python3         

The two processes with PIDs 860 and 810 are communicating; 810 being the server in this case. We can see this by visually parsing the netstat output or grep for it.

Also, say we wanted to see what clients are talking with PID 810, we could do lsof -p 810:

COMMAND PID USER   FD      TYPE             DEVICE  SIZE/OFF    NODE NAME
<snip>
python3 810 user    8u     IPv4              35702       0t0     TCP 127.0.0.1:5000 (LISTEN)
python3 810 user   10u     IPv4            4682120       0t0     TCP 127.0.0.1:5000->127.0.0.1:46858 (ESTABLISHED)

Here we can identify the endpoint that is communicating with our process, but not the PID. To identify the other PID, we could do lsof -i :46858:

COMMAND PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
python3 810  user   10u  IPv4 4682120      0t0  TCP localhost:5000->localhost:46858 (ESTABLISHED)
nginx   860 nginx   18u  IPv4 4681280      0t0  TCP localhost:46858->localhost:5000 (ESTABLISHED)

Further down in the netstat output is UNIX sockets:

Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
<snip>
unix  2      [ ACC ]     STREAM     LISTENING     21936    1/systemd            /run/dbus/system_bus_socket
<snip>
unix  3      [ ]         STREAM     CONNECTED     28918    648/dbus-daemon      /run/dbus/system_bus_socket

We can see that both of these processes are using the UNIX socket at /run/dbus/system_bus_socket. So if you knew one of the processes, looking at this, you should be able to determine the other end. lsof can be used again in this case, and can also be pointed at the socket file like lsof /run/dbus/system_bus_socket.

I realize this is a little convoluted and a little complicated, but I hope it helps. Note that other types of IPC that use some kind of file/handle (such as pipes) can be traced using lsof as well.

  • Thanks. (1) "The two processes with PIDs 860 and 810 are communicating; 810 being the server in this case". How do you know which is the server which is client? – Tim Dec 3 '18 at 22:50
  • @Tim because you can see a separate entry for the server's socket in a listen state. – multithr3at3d Dec 4 '18 at 1:24
  • netstat will only print the name for a unix socket in the case where the socket is bound to that path/name, not when it's connected to it. For instance, if you start xclock it will connect to the X11 socket deducted from the DISPLAY envvar, but you won't be able to tell from the output of netstat -xp | grep xclock which socket it's connected to. – mosvy Dec 4 '18 at 2:07
  • @mosvy Does a socket binding to a pathname means the relation between a socket and its socket file? "when it's connected to it", do you mean a socket connects to another socket? – Tim Dec 4 '18 at 3:07
  • @Tim Any socket may have two addresses it's in "relation" with -- the address to which it's bound (with bind(2), returned by getsockname(2)), and the address to which it's connected (with connect(2), returned by getpeername(2)). In the case of unix sockets a) the addresses are paths in the filesystem (or simple strings on linux which also supports "abstract" sockets) b) a connected socket may be anonymous, with no address it's bound to (the kernel doesn't bind it to an automatic address, as it does with tcp sockets). Most "client" unix sockets are like that. – mosvy Dec 4 '18 at 3:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.