13

I want to observe a socket status periodically, so I need to check the socket status by command.

Currently I list all listening sockets by ss and filter them by grep.

ss -l | grep -q /run/php/php7.0-fpm.sock

Is there better way to check socket's status?

3
  • 1
    In my Debian 9 socat UNIX-LISTEN:/foo/socket -, socat UNIX-LISTEN:/foo//socket -, socat UNIX-LISTEN:/foo/bar/../socket - and cd /foo/ && socat UNIX-LISTEN:socket - make ss -l show /foo/socket, /foo//socket, /foo/bar/../socket and socket respectively (not at the same time, of course). The socket is /foo/socket each time. On the other hand cd /foo/bar/ && socat UNIX-LISTEN:socket - makes ss -l show socket as well. Oh well. A better way is welcome indeed. Commented Dec 11, 2019 at 20:46
  • Not really. The kind of netlink sockets ss and lsof use to communicate with the kernel (sock_diag) do not support passive monitoring, like route netlink sockets do. You better just remove that socket and inotifywait its containing directory; any program listening on a unix socket will create the directory entry when binding to its path.
    – user313992
    Commented Dec 11, 2019 at 23:12
  • Other mentioned limitations of ss and lsof are because of their inept, user-hostile design: they really can get the info to match unix sockets to files (UNIX_DIAG_VFS), but either don't bother to ask for it, or don't know how to use it.
    – user313992
    Commented Dec 11, 2019 at 23:18

3 Answers 3

17

You can get some information by trying to connect, pass nothing and accept nothing before disconnecting.

socat -u OPEN:/dev/null UNIX-CONNECT:/run/php/php7.0-fpm.sock

There are at least four possible outcomes:

  • If the socket does not exist then the error will be No such file or directory and the exit status will be 1.

  • If you have no write access to the socket then the error will be Permission denied and the exit status will be 1. In this case you cannot tell if there's a process listening.

  • If you have write access to the socket and there is no listening process then the error will be Connection refused and the exit status will be 1.

  • If you have write access to the socket and there is a process listening then the connection will be established. The command will send nothing (like cat /dev/null), it will not try to receive anything (because of -u), so it will exit almost immediately. The exit status will be 0.

    The connection gets established, briefly but still. The listening process may be configured to accept just one connection, serve it and exit; or to accept one connection at a time. In such case the probing connection will saturate the limit; this is undesirable. However in practice I expect vast majority of listening processes to be able to serve multiple connections and gracefully deal with clients who disconnect ruthlessly.

Notes:

  • You need to parse stderr to tell apart cases that generate exit status 1.
  • The procedure tells nothing about what process is listening.
2
  • 1
    Beware of false negatives when dealing with sockets owned by root. If you can't read the socket, socat can't read it either, so you need to elevate privileges (sudo, or doas) to verify anything
    – smac89
    Commented Apr 13, 2021 at 21:43
  • Can use option -ddd for better view: socat -u -ddd OPEN:/dev/null UNIX-CONNECT:/run/php/php7.0-fpm.sock
    – rlf89
    Commented Mar 23, 2023 at 6:28
1

You can match it by the device and inode number:

ss -elx | grep -w "$(stat -c 'ino:%i dev:0/%d' /run/php/php7.0-fpm.sock)"

Give the -q option to grep if all you care about is its exit status (0 = success if there's a process listening on that file).

See related answer and the one linked from there for an explanation and gotchas, especially the part about the buggy format of the device number returned by ss.

Trying to connect to a socket to determine if something is listening on it is like biting someone to see if they're still alive ;-)

0

If you had just wanted to check a port being open or not, I would have suggested using telnet like so:

telnet localhost <port>

However it looks like you want to script it out and keep checking at regular intervals. In addition to the excellent answers above, here is an example on how to do that.

I acknowledge the SE post by Chuss and am adding some information on how it works.

host=localhost; port=222
r=$(bash -c 'exec 3<> /dev/tcp/'$host'/'$port';echo $?' 2>/dev/null)
if [ "$r" = "0" ]; then
      echo "$host $port is open";
 else
      echo "$host $port is closed"; 
fi

Here are the lines explained:

  • bash -c executes the the command in an empty environment.
  • exec 3<> /dev/tcp/'$host'/'$port' opens /dev/tcp/'$host'/'$port' for reading and writing.
  • echo $? records the exit code of the last command (0 or non-zero); the variable "r" gets this value.

Now we have the variable $r which can be 0(open) or non-zero(closed). Based on that you can do something like echo the result, write to a log file, or email the output. You can run this as a cron job.

HTH.

4
  • Which "SE post by Chuss" are you refering to?
    – bfontaine
    Commented Mar 4, 2022 at 17:13
  • @bfontaine You can click on the link to open that page. For ready reference, here it is: unix.stackexchange.com/questions/86556/… -- not sure why that post got upvoted multiple times and my copy-paste (with due acknowledgement) got downvoted. Commented Mar 6, 2022 at 7:10
  • Thank you! I was asking because in your answer the link points to Chuss’ profile, not to their answer.
    – bfontaine
    Commented Mar 6, 2022 at 9:26
  • 1
    I believe that your post was downvoted because the answer is not addressing the status of a socket.
    – Kyr
    Commented May 24, 2022 at 12:56

You must log in to answer this question.

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