2017-03-06 66 views
1

程序my_prog将在启动后启动。它创建了一个由root:root拥有的Unix域套接字/tmp/my_prog.sock如何设计systemd路径单元?

我尝试做如下:

  • 更改套接字文件的所有者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得到执行的太快,让我这样意外的结果:

  • chmod运行之前my_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 

编辑

继@马克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' 

回答

0

通过你的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身份运行,可以提高安全性和避免需要chown,通过使用User=Group=指令来运行该服务为不同的用户。这将创建该用户拥有的套接字而不是root。

+0

谢谢!绝对可执行文件路径解决了我的第二个问题。我的第一个问题依旧。 –

+0

查看更新的答案。 –

+1

'.socket'在编辑期间是一个错字。 'User ='和'Group ='解决了我的问题,我认为这是最优雅的设计。非常感谢! –