2

FIFO is problematic in use because both reader and writer have to open it – if one of them is being late, the other one is blocked inside the operating system.

I have to implement a publishing mechanism – a program publishes its logs, and if anyone "cares" to listen i.e. opens the publishing channel, he receives the messages. If no one "cares", the messages vanish, no problem. Support for no more than single listener – also no problem. What can I use?

Digger
  • 23
  • 1
    Why not use just syslog(3) or logger(1) instead? But if you really want to invent your own logging mechanism, using named pipes is about the worst idea you can get (even if you actually can open them without blocking, if you open them in rw mode, eg. exec 7<>/path/to/fifo) –  Mar 18 '20 at 23:48

1 Answers1

5

You can broadcast UDP. This is the sender part, pipe anything to it:

socat - UDP-DATAGRAM:127.255.255.255:50011,sourceport=50022,broadcast

Receivers use this, they can join or leave the party anytime:

socat - UDP-LISTEN:50011,bind=127.255.255.255,sourceport=50022,reuseaddr

Notes and explanations:

  • UDP does not guarantee that packets will arrive in order (see this)
  • 50011 and 50022 are port numbers you choose.
  • The address 127.255.255.255 means the sender broadcasts through the loopback interface, you can adjust this to broadcast in LAN if you wish.
  • Similarly bind=127.255.255.255 should limit receivers to this interface, so you don't have to worry about (rogue?) UDP packets from elsewhere, if any.
  • A fixed sourceport for two reasons:
    • receivers wont "see" another (rogue?) sender that broadcasts to the same address and port but from another (maybe random) source port;
    • after the sender is terminated for whatever reason, you can restart it and all the existing receivers won't see the difference; if the sender used random source port, the existing receivers in general wouldn't "see" the new sender because they would stay fixed on the old source port.
  • reuseaddr allows multiple receivers to coexist.
  • Technically you can add reuseaddr to the sender part, this allows you to run multiple senders. It may lead to interleaved output on the receiving side, not recommended.
  • A running sender will prevent another (rogue?) sender from using exactly the same tuple of addresses and ports. However as soon as your sender is terminated, another one can take its place. If you have root access you can choose sourceport to be lower than 1024. Most OS-es won't let regular users bind to these ports (the name is "privileged ports"); this way users won't be able to impersonate your sender even when it's dead. Receivers run by regular users, however, can use a privileged port as their sourceport. To ensure only root can receive, change the other port (50011 in my example) to a privileged one.