2017-03-06 39 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 ='解決了我的問題,我認爲這是最優雅的設計。非常感謝! –