I use socat with following init script on debian 7.2 with sysVinit. It works perfectly:

#!/bin/bash
DESC=socat
DAEMON=/usr/bin/socat
LIB=/usr/lib/socat
SOCAT_ARGS="-d -d -lf /var/log/socat.log"

[ ! -f /etc/default/socat.conf ] || . /etc/default/socat.conf

. /lib/lsb/init-functions

PATH=/bin:/usr/bin:/sbin:/usr/sbin

[ -x $DAEMON ] || exit 0

#
#       Try to increase the # of filedescriptors we can open.
#
maxfds () {
        [ -n "$SOCAT_MAXFD" ] || return
        [ -f /proc/sys/fs/file-max ] || return 0
        [ $SOCAT_MAXFD -le 4096 ] || SQUID_MAXFD=4096
        global_file_max=`cat /proc/sys/fs/file-max`
        minimal_file_max=$(($SOCAT_MAXFD + 4096))
        if [ "$global_file_max" -lt $minimal_file_max ]
        then
                echo $minimal_file_max > /proc/sys/fs/file-max
        fi
        ulimit -n $SOCAT_MAXFD
}

start_socat() {
        start-stop-daemon --quiet --start \
                --pidfile /var/run/socat.$NAME.pid \
                --background --make-pidfile \
                --exec $DAEMON -- $SOCAT_ARGS $ARGS < /dev/null
}

stop_socat() {
        start-stop-daemon --stop --quiet --pidfile /var/run/socat.$NAME.pid --exec $DAEMON
        rm -f /var/run/socat.$NAME.pid
}

start () {
        echo "Starting $DESC:"

        maxfds
        umask 027
        cd /tmp
        if test "x$AUTOSTART" = "xnone" -o -z "x$AUTOSTART" ; then
                echo "Autostart disabled."
                exit 0
        fi
        for NAME in $AUTOSTART ; do
                ARGS=`eval echo \\\$SOCAT_$NAME`
                echo $ARGS
                start_socat
                echo " $NAME $ARGS"
        done
        return $?
}

stop () {
        echo -n "Stopping $DESC:"

        for PIDFILE in `ls /var/run/socat.*.pid 2> /dev/null`; do
                NAME=`echo $PIDFILE | cut -c16-`
                NAME=${NAME%%.pid}
                stop_socat
                echo -n " $NAME"
        done
}

case "$1" in
    start)
        log_daemon_msg "Starting socat" "socat"
        if start ; then
                log_end_msg $?
        else
                log_end_msg $?
        fi
        ;;
    stop)
        log_daemon_msg "Stopping socat" "socat"
        if stop ; then
                log_end_msg $?
        else
                log_end_msg $?
        fi
        ;;
    reload|force-reload|restart)
        log_daemon_msg "Restarting socat" "socat"
        stop
        if start ; then
                log_end_msg $?
        else
                log_end_msg $?
        fi
        ;;
        *)
        echo "Usage: /etc/init.d/$NAME {start|stop|reload|force-reload|restart}"
        exit 3
        ;;
esac

exit 0

However after an upgrade to debian 7.4 the system changed to systemd. So to run the same script on systemd I added a service that wrappes the /etc/init.d/socat script:

[Unit]
Description=Socat

[Service]
ExecStart=/etc/init.d/socat start
ExecStop=/etc/init.d/socat stop

[Install]
WantedBy=multi-user.target

When I start the service it is started but stops directly:

Loaded: loaded (/usr/lib/systemd/system/socat.service; enabled)
Active: inactive (dead) since Fri, 18 Apr 2014 14:09:46 +0200; 4s ago Process: 5334 ExecStart=/etc/init.d/socat start (code=exited, status=0/SUCCESS) CGroup: name=systemd:/system/socat.service

Am I missing something?

  • Am I missing something? Yes, you missed actually migrating the init.d script to systemd :) – Piotr Dobrogost Mar 7 '17 at 11:13
up vote 8 down vote accepted

Just figured out that I have to use

Type=forking

like described in http://www.freedesktop.org/software/systemd/man/systemd.service.html.

If set to forking, it is expected that the process configured with ExecStart= will call fork() as part of its start-up. The parent process is expected to exit when start-up is complete and all communication channels are set up. The child continues to run as the main daemon process. This is the behavior of traditional UNIX daemons. If this setting is used, it is recommended to also use the PIDFile= option, so that systemd can identify the main process of the daemon. systemd will proceed with starting follow-up units as soon as the parent process exits.

For socat, I use a pure systemd approach. This is an example for a serial loopback:

[Unit]
Description=Socat Serial Loopback
#Before=my-other.service

[Service]
Type=simple
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=socat-serial-lo

ExecStart=/usr/bin/socat -d -d pty,raw,echo=0,link=/tmp/seriallo-a pty,raw,echo=0,link=/tmp/seriallo-b
Restart=always

[Install]
WantedBy=multi-user.target

This can be written to /etc/systemd/system/socat-serial-lo.service (in Ubuntu 16.04+), and then:

systemctl daemon-reload
systemctl start socat-serial-lo
systemctl enable socat-serial-lo  # (to start it during bootup)

One advantage of this method is that the command line defined by ExecStart can be tested directly from command line without alterations, in order to test the command.

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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