如何设计systemd路径单元?

时间:2017-03-06 15:07:42

标签: systemd

程序my_prog将在启动后启动。它创建了/tmp/my_prog.sock拥有的Unix域套接字root:root

我正在努力做到以下几点:

  • 创建套接字文件的所有者后,将其更改为www-data:www-data
  • 程序退出后删除套接字文件。

这是我的单元文件my_prog.service的第一个版本:

[Unit]
Description=My Program
After=network.target

[Service]
ExecStart=/usr/local/bin/my_prog
ExecStartPost=chmod www-data:www-data /tmp/my_prog.sock
ExecStopPost=rm -f /tmp/my_prog.sock

[Install]
WantedBy=multi-user.target

这个版本有两个问题:

  • 永远不会更改/tmp/my_prog.sock的所有者 - 始终root:root

  • 此服务停止后,
  • /tmp/my_prog.sock永远不会被删除。

我想命令chmodrm过早执行会给我带来意想不到的结果:

  • chmodmy_prog完成创建套接字文件之前运行,
  • rmmy_program退出之前运行(my_program禁止其套接字文件在运行时被删除?)。

以下是我的第二个版本,它未能给我正确的结果:

档案my_prog.service

[Unit]
Description=My Program
After=network.target

[Service]
ExecStart=/usr/local/bin/my_prog

[Install]
WantedBy=multi-user.target

档案my_prog-socket.path

[Unit]
Description=My program - notify socket existence

[Path]
PathExists=/tmp/my_prog.sock

档案my_prog-socket.service

[Unit]
Description=My program - change owner and remove socket

[Service]
ExecStart=chown www-data:www-data /tmp/my_prog.sock
ExecStopPost=rm -f /tmp/my_prog.sock

我已经完成了所有技巧。 我的单位文件出了什么问题? 是否有比上面更优雅的设计?

谢谢!

P.S。:对于那些感兴趣的人,这个旧版本/etc/init.d/my-prog至少按预期工作:

#!/bin/sh
### BEGIN INIT INFO
# Provides:         my-program
# Default-Start:    2 3 4 5
# Default-Stop:     0 1 6
# Short-Description:    My Program
# Description:      My Program
### END INIT INFO


PATH=/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/bin/my_prog
NAME=my-program
DESC="My Program"
SCRIPTNAME=/etc/init.d/$NAME
PIDFILE=/var/run/my-prog.pid
SOCKET_FILE="/tmp/my-prog.sock"

test -x $DAEMON || exit 0

grant_socket_access()
{
    #Wait program to create socket.
    count=1
    while [ "$count" -lt "50" ]
    do
        if [ -S $SOCKET_FILE ]
        then
            chown www-data:www-data $SOCKET_FILE
            return 0
        fi
        sleep 0.2
        count=`expr $count + 1`
    done
    echo >&2 "$NAME fails to grant access to Unix socket file: $SOCKET_FILE"
    return 1
}

. /lib/lsb/init-functions

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" $NAME
        rm -f $SOCKET_FILE
        if start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -b -m
        then
            grant_socket_access
        else
            rm -f $SOCKET_FILE
        fi
        log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" $NAME
        rm -f $SOCKET_FILE
        if start-stop-daemon --stop --retry TERM/10/KILL/5 --quiet --pidfile $PIDFILE --exec $DAEMON --remove-pidfile
        then
            log_daemon_msg "$DESC" "$NAME stopped"
            log_end_msg 0
        else
            log_end_msg 1
        fi
        ;;
    reload|force-reload)
        log_daemon_msg "Reloading $DESC" $NAME
        rm -f $SOCKET_FILE
        if start-stop-daemon --stop --signal HUP --quiet --pidfile $PIDFILE --exec $DAEMON
        then
            grant_socket_access
            log_end_msg $?
        else
            log_end_msg 1
        fi
        ;;
    restart)
        log_daemon_msg "Restarting $DESC" $NAME
        $0 stop
        $0 start
        ;;
    status)
        status_of_proc -p "$PIDFILE" "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
    *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|status}" >&2
        exit 1
        ;;
esac

exit 0

修改

根据@Mark Stosberg友情提供的食谱,我已经修改了原来的第一个版本,刚才有/bin/chown/bin/rm

我从新版本中的第ExecStopPost=/bin/rm -f /tmp/my_prog.sock行获得了所需的结果。但是,ExecStart=/bin/chown www-data:www-data /tmp/my_prog.sock会输出此错误:

chown[8388]: /bin/chown: connot access '/tmp/my_prog.socket'

2 个答案:

答案 0 :(得分:1)

通过systemd-analyze verify ./your-file.service运行脚本会发现问题:

[/home/mark/tmp/t.service:7] Executable path is not absolute, ignoring: chmod www-data:www-data /tmp/my_prog.sock                                   
[/home/mark/tmp/t.service:8] Executable path is not absolute, ignoring: rm -f /tmp/my_prog.sock  

man systemd.service中的文档记录了可执行路径必须是绝对路径的要求。

您的错误是指扩展名为.socket的文件,但您的示例显示的是.sock扩展名。确认您在所有地方始终使用.sock.socket

如果您的服务不需要以root用户身份运行,则可以通过使用chownUser=指令来提高安全性并避免Group=的需要作为不同用户的服务。这将创建一个由该用户而不是root用户拥有的套接字。

答案 1 :(得分:0)

  

谢谢!绝对可执行路径解决了我的第二个问题。我的第一个问题仍然存在

您的第一个问题是chmod不使用“ owner:group”,您真的想要“ chown”

例如:

ExecStartPost = 小丑 www-data:www-data /tmp/my_prog.sock