zoukankan      html  css  js  c++  java
  • daemon 启动system V init 和 systemd 配置

    先试着写一个udpserver的daemon

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define PORT 4444
    #define FDMAX 64
    void initdaemon();
    int main()
    {
        #ifdef DAEMON
            initdaemon();
        #endif
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if(fd < 0)
            return -1;
        struct sockaddr_in server, client;
        server.sin_family = AF_INET;
        server.sin_port = htons(PORT);
        server.sin_addr.s_addr = htonl(INADDR_ANY);
        bind(fd, (const struct sockaddr *)&server, sizeof(struct sockaddr));
        socklen_t len  = sizeof(struct sockaddr);
        char buff[2048] = {0};
        while(1)
        {
            recvfrom(fd, buff, 2048, 0,(struct sockaddr *)&client, &len);
           // printf("%s send msg: %s 
    ", inet_ntoa(client.sin_addr), buff);
            sendto(fd, "OK", 2, 0, (const struct sockaddr *)&client, len);
        }
    }
    void initdaemon()
    {
        pid_t pid = fork(); //第一次fork 是因为创建会话的进程不能是进程组长,否则setsid会失败。
        if(pid > 0)
        {
            _exit(0);
        }
        else if(pid < 0)
        {
            _exit(1);
        }
        if(setsid() < 0)
            _exit(1);
        pid_t id = fork();//第二次fork是因为当前进程是会话组长 他有可能会获取控制终端,为了不让它获得控制终端,不让它成为组长。
        if(id > 0){
            _exit(0);
        }
        else if(id < 0)
        {
            _exit(1);
        }
        int i = 0;
        chdir("/");
        for(i; i < FDMAX; ++i)
            close(i);
        open("/dev/null", O_RDONLY);
        open("/dev/null", O_RDWR);
        open("/dev/null", O_RDWR); //将0 1 2重定向
    }
    gcc -DDAEMON udpserver.c -o udpserver添加宏DAEMON进行编译

    下面是测试client端:

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define PORT 4444
    int main(int argc, char *argv[])
    {
        if(argc != 2)
        {
            printf("./udpclient IP
    ");
            return 1;
        }
        int fd = socket(AF_INET, SOCK_DGRAM, 0);
        if (fd < 0)
            return 1;
        struct sockaddr_in server;
        server.sin_family = AF_INET;
        server.sin_port = htons(PORT);
        if (!inet_pton(AF_INET, argv[1], (void *)&server.sin_addr))
        {
            printf("IP error
    ");
            return -1;
        }
        char buff1[2048] ="sdfsdf";
        char buff2[2048] = {0};
        socklen_t size = sizeof(struct sockaddr);
        while(1)
        {
            sendto(fd, buff1, 2048, (const struct sockaddr *)&server, size);
            sleep(5);
            recvfrom(fd, buff2, 2048, 0, NULL, NULL);
            printf("recv : %s
    ", buff2);
        }
    
    }

    先看一下system v init管理服务的一种写法:
    我们可以看到在/etc/init.d 下面有很多脚本文件, 当系统启动时,init进程会根据不同的运行级别去执行不同的/etc/rcN.d 里面的脚本文件并会自动加上start参数,我们看一下sshd的例子:

    set -e
    
    # /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon
    
    test -x /usr/sbin/sshd || exit 0
    ( /usr/sbin/sshd -? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0
    
    umask 022
    
    if test -f /etc/default/ssh; then
        . /etc/default/ssh
    ficase "$1" in
      start)
        check_for_upstart 1
        check_privsep_dir
        check_for_no_start
        check_dev_null
        log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd" || true
        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
      stop)
        check_for_upstart 0
        log_daemon_msg "Stopping OpenBSD Secure Shell server" "sshd" || true
        if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/sshd.pid; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
    
      reload|force-reload)
        check_for_upstart 1
        check_for_no_start
        check_config
        log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" "sshd" || true
        if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
    
      restart)
        check_for_upstart 1
        check_privsep_dir
        check_config
        log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd" || true
        start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/sshd.pid
        check_for_no_start log_end_msg
        check_dev_null log_end_msg
        if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
            log_end_msg 0 || true
        else
            log_end_msg 1 || true
        fi
        ;;
    
      try-restart)
        check_for_upstart 1
        check_privsep_dir
        check_config
        log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd" || true
        RET=0
        start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/sshd.pid || RET="$?"
        case $RET in
            0)
            # old daemon stopped
            check_for_no_start log_end_msg
            check_dev_null log_end_msg
            if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
                log_end_msg 0 || true
            else
                log_end_msg 1 || true
            fi
            ;;
            1)
            # daemon not running
            log_progress_msg "(not running)" || true
            log_end_msg 0 || true
            ;;
            *)
            # failed to stop
            log_progress_msg "(failed to stop)" || true
            log_end_msg 1 || true
            ;;
        esac
        ;;
    
      status)
        check_for_upstart 1
        status_of_proc -p /var/run/sshd.pid /usr/sbin/sshd sshd && exit 0 || exit $?
        ;;
    
      *)
        log_action_msg "Usage: /etc/init.d/ssh {start|stop|reload|force-reload|restart|try-restart|status}" || true
        exit 1
    esac
    
    exit 0

    写法也就是大致这个样子的利用shell 里的case 给不同参数运行不同的function 至于start-stop-daemon的用法可以查阅man page。
    我们就可以将我们的udpserver 放到/usr/bin/目录下面,然后在/etc/init.d/目录下加上udp_server 脚本文件写法如下:

     #!/bin/bash
    SERVER=/usr/bin/udpserver
    if [ ! -e $SERVER ];then
        exit 1
    fi
    case "$1" in
        start)
            if [ -n "`pidof $SERVER`" ];then
                echo "Udpserver is running......"
            else
                $SERVER
            fi
        ;;
    
        stop)
            PID=`pidof /usr/bin/udpserver`
            [ -n "$PID" ] && kill -9 $PID
        ;;
    
        restart)
            PID=`pidof $SERVER`
            [ -n "$PID" ] && kill -9 $PID
            $SERVER
        ;;
    
        *)
            exit 1
        ;;
    
    esac

    再将你需要运行的等级目录下添加连接/etc /rc2.d/目录下K开头表示不启动服务,S打头表示启动服务 建立连接 ln -s ../init.d/udp_server S99udpserver , 表名开机启动 S后的数字字母等表示启动顺序。如此就可以实现system v init类型的启动服务。

    若以systemd形式 将更为简单方便 此时就不需要udpserver 是一个daemon 可去掉宏进行编译。

    在/etc/systemd/system/下建立文件udpserver.service 文件 内容大概为

    [Unit]
    Description=my dup server
    After=network.target
    
    [Service]
    EnvironmentFile=
    ExecStart=/usr/bin/udpserver
    ExecReload=/bin/killall udpserver
    KillMode=process
    Restart=on-failure
    
    [Install]
    WantedBy=multi-user.target

    然后再执行 systemctl daemon-reload systemctl enable udpserver即可开机自启动。
    systemctl start /stop/reload控制服务。journalctl可以查看启动日志。
    总得来说还是systemd这种形式较为简单,它还有较好的日志系统,方便管理 不用将服务写为daemon。

  • 相关阅读:
    House of hello恶搞包之真假辨别
    Window phone用手机来控制电脑的多媒体播放
    《你是我的小羊驼》游戏ios源码
    打地鼠游戏ios源码
    Android系统的架构
    魔兽塔防游戏android源码
    抢滩登陆游戏android源码
    Java学生管理系统项目案例
    UITextView如何关闭键盘
    view上添加点手势 button无法响应点击事件
  • 原文地址:https://www.cnblogs.com/MaAce/p/7755701.html
Copyright © 2011-2022 走看看