Thanks to everyone for the help here, especially tybalt89.

Bringing it all together and testing it on an Ubuntu 22.04 VM, I have this simplified perl script:

#!/usr/bin/perl # Minimal systemd socket activated service # Put together based on responses from: https://www.perlmonks.org/?nod +e_id=11157093 use strict; use warnings; use English; $OUTPUT_AUTOFLUSH = 1; # AKA $| # Important. We need to know the remote IP address. my $remote_addr = $ENV{REMOTE_ADDR}; printf "Greetings %s what is your command?\n", $remote_addr; # printf "%s = %s\n", $_, $ENV{$_} foreach sort keys %ENV; # Us +ed to get the rest of the environment. # Code here to check that $remote_addr is authorised to connect, and w +hich remote commands it may call. # Need to close the socket & refuse futher commands $remote_addr is no +t authorised. while( my $cmd = <> ) { if( $cmd =~ m/^sleep (\d+)/ ) { my $snooze_time = $1; printf "Will sleep for $snooze_time seconds\n"; sleep $snooze_time; print "... ZZZ ... Yawn ... What next oh master?\n"; } # NB: In real life there are lots of other commands and many take +some time to process. else { print "I did not understand that. What next oh master?\n"; } }

With two systemd unit files:

The socket:

/etc/systemd/system/pfs.socket

[Unit] Description=perl forking socket PartOf=pfs.service [Socket] ListenStream=2345 BindIPv6Only=both Accept=yes MaxConnections=12 [Install] WantedBy=sockets.target

And the service:

/etc/systemd/system/pfs@.service

[Unit] Description=perl forking server After=network.target nss-user-lookup.target Requires=pfs.socket [Service] ExecStart=/root/path/to/minimal_systemd_socket_activated_service.pl StandardInput=socket [Install] Also=pfs.socket WantedBy=multi-user.target

Once all three files are installed on the sever:

It should then be possible to test the service:

echo "sleep 30" | nc localhost 2345 -NC

Notes and observations:

Like a CGI script, when the socket activated service is running, STDIN and STDOUT are the socket to the remote client, so printf debugging and logging does not work as expected.

Similar to a cron job, the socket activated service gets very few environment variables set. It is possible to add Environment="variable=value" entries into the Service stanza of the pfs@.service file.

The service file should have an @ symbol in the name. It is not a mistake. In other types of systemd units, the @ symbol means that the service is parameterised, and we should expect to see a %i placeholder in the service unit file. For the socket activated service, the socket sets up the parameters when it invokes the service.

I connected to the service to start a lengthy sleep, then ran systemctl status pfs.socket

This gave an extra Triggers entry that is not show when the socket is idle.

root@Ubuntu:~# systemctl status pfs.socket
● pfs.socket - perl forking socket
     Loaded: loaded (/etc/systemd/system/pfs.socket; enabled; vendor preset: enabled)
     Active: active (listening) since Sun 2024-01-21 10:18:43 GMT; 9min ago
   Triggers: ● pfs@5-127.0.0.1:2345-127.0.0.1:39394.service
     Listen: :::2345 (Stream)
   Accepted: 6; Connected: 1;
      Tasks: 0 (limit: 9361)
     Memory: 8.0K
        CPU: 1ms
     CGroup: /system.slice/pfs.socket

I was then able to get the status of the temporary service:

root@Ubuntu:~# systemctl status pfs@5-127.0.0.1:2345-127.0.0.1:39394.service
● pfs@5-127.0.0.1:2345-127.0.0.1:39394.service - perl forking server (127.0.0.1:39394)
     Loaded: loaded (/etc/systemd/system/pfs@.service; disabled; vendor preset: enabled)
     Active: active (running) since Sun 2024-01-21 10:27:42 GMT; 11s ago
TriggeredBy: ● pfs.socket
   Main PID: 3225 (minimal_systemd)
      Tasks: 1 (limit: 9361)
     Memory: 1.2M
        CPU: 5ms
     CGroup: /system.slice/system-pfs.slice/pfs@5-127.0.0.1:2345-127.0.0.1:39394.service
             └─3225 /usr/bin/perl /root/path/to/minimal_systemd_socket_activated_service.pl

And investigate the environment variables of that service

root@Ubuntu:~# cat /proc/3225/environ | xargs -0 -n1
LANG=en_GB.UTF-8
LANGUAGE=en_GB:en
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
REMOTE_ADDR=127.0.0.1
REMOTE_PORT=39394
INVOCATION_ID=73c1fa9b1e8b45c0a557538dce370fd6
SYSTEMD_EXEC_PID=3225

In reply to Re: Systemd socket activated service in perl by chrestomanci
in thread Systemd socket activated service in perl by chrestomanci

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.