systemd,upstart, systemV服务启动编写

systemd,upstart, systemV是LInux系统三种主流的启动方式。但是技术的发展,systemV以及upstart的一些局限,systemd已经成为当下最主要的启动方式了,systemd的最大优点就是可以让开机启动的服务并行运行,减少了开机运行的时间。

systemd管理的服务的配置文件存放在三个目录,三个目录分别是:
/usr/lib/systemd/system/ 安装包自带的service配置文件存放的位置
/etc/systemd/system/ systemctl enable创建的service文件(当你手动添加了一个服务的配置文件,并且还要让它开机自启动运行,那么就必须执行systemctl enable xxx.service)。通常情况下,这些文件基本都是/usr/lib/systemd/system/下的软连接,而且是以target组分类存放的的;也或者是用户手动添加的服务的service文件。
/run/systemd/system/ 运行时创建的service文件;优先级/etc/systemd/system/ > /run/systemd/system/ > /usr/lib/systemd/system/
谈到systemd的target组,他其实就和systemV的runlevel(运行等级)对应。

用户自己手动在systemd下增加一个服务,就需要在/etc/systemd/system下创建一个service配置文件,当然在 /usr/lib/systemd/system/创建也可以。配置文件大致如下:

[Unit]
Description=Systemd service test
After=syslog.target #在syslog.target中的服务启动后再启动

[Service] #Unit类型
ExecStart=/bin/bash -c "exec FOO.sh" #这样执行,即使FOO.sh有while死循环,systemctl start/top 也会执行完就退出
ExecStart=Other CMD
ExecStartPost=/bin/bash -c "exec   FOO1.sh" #ExecStart执行完后执行这个

Restart=on-failure
RestartSec=30s
Type=simple

[Install]
WantedBy=multi-user.target #systemctl enable 后,就会在/etc/systemd/multi-user.target.wants下创建一个软连接到这里

Service项中的ExecStart是必须的,但是其他的,比如ExecStartPost,ExecStop,都是可选的。对于ExecStop,就是停止服务所需要运行的脚本,看到这里可能会产生疑问,没有设定ExecStop,那么怎么停止服务呢,答案是系统中已经记录已经通过systemd启动的服务,执行systemctl stop 就会向对应的服务发送SIGTERM信号,默认5分钟如果没有收到对应服务的答复,那么就会在发送SIGKILL信号强行终止服务。
需要说明一下的就是,用户手动起的服务,是没办法通过这三个工具去停止或者查询状态的,因为systemd没办法监控"
The systemctl utility does not communicate with services that have not been started by systemd. When systemd starts a system service, it stores the ID of its main process in order to keep track of it. The systemctl utility then uses this PID to query and manage the service. Consequently, if a user starts a particular daemon directly on the command line, systemctl is unable to determine its current status or stop it."

在对应的目录编写好service配置文件后,执行systemctl daemon-reload后就可以通过syetemctl start/stop去停起服务了
如果要加到开机自启动,那么还要执行systemctl enable xxx.service,这个服务就加到了对应的target组了。
具体参考
https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/chap-Managing_Services_with_systemd.html
https://wiki.ubuntu.com/SystemdForUpstartUsers
http://www.jinbuguo.com/systemd/systemd.service.html

关于upstart,它是ubuntu主推的,向下兼容systemV,他的配置文件是/etc/init/目录下以.conf结尾的文件。因此在upstart管理服务的系统中要加入一个服务,就在/etc/init/目录增加一个服务对应的配置文件即可。配置文件的大致内容如下:
/etc/init/FOO.conf

description "uwsgi service"
start on runlevel [2345]  #哪些运行等级自动运行该服务
stop on runlevel [06]  #哪些运行等级不自动运行该服务

env LANG=en_US.UTF-8
limit nofile 65535 65535

script
    exec cmd #服务启动时执行的脚本
end script

post-start script
    exec cmd #服务启动后执行的脚本
end script

respawn
respawn limit 10 5

对于更多脚本语法和配置,可参照http://upstart.ubuntu.com/
或者:http://upstart.ubuntu.com/cookbook/
想要看到start或者stop的大概执行过程,可以先sudo initctl log-priority debug改变initctl的日志级别,然后就可以在/var/log/syslog中查看执行过程的日志了。

关于systemV,三者中最传统,最古老的服务启动方式,他的配置文件存放在/etc/init.d/目录下,这个目录下是服务停起的直接控制脚本,而关于开机时启动哪些服务,这个是根据runlevel决定的,系统开机分为7个运行等级,分别是0到6,每个运行等级所需要运行的服务存放在/etc/rc.d/rc(0,1...6).d/目录下,这个目录下的脚本是/etc/init.d/目录下脚本的软连接。systemV的脚本样例如下:

#!/bin/bash
#
# chkconfig: 2345 80 20  #chkconfig --add service 会根据这里的设定,在对应的启动级别加上这个服务
# description: Agent daemon service
# /etc/rc.d/init.d/xxxserver

name=xxxservice
pid_file="/var/run/${name}.pid"
stdout_log="/var/log/${name}_success.log"
stderr_log="/var/log/${name}_error.log"
cmd="需要启动的服务的命令"

# Get function from functions library
. /etc/init.d/functions  #关键是这个文件,这个文件中有很多有用的函数

get_pid() {
    cat "$pid_file"
}

is_running() {
    [ -f "$pid_file" ] && ps -p `get_pid` > /dev/null 2>&1
}

# Start the host agent
start() {
        if is_running; then
            echo "$name already started"
        else
            echo  "Starting $name ..."
            date -R >> "$stdout_log" 2>> "$stderr_log"
            $cmd >> "$stdout_log" 2>> "$stderr_log" &
            ### Create the lock file ###
            echo $! > "$pid_file"

            if ! is_running; then
                echo "Unable to start $name, see $stdout_log and $stderr_log"
                exit 1
            fi
            echo "$name startup success"
        fi
}

# Stop the host agent
stop() {
    if is_running; then
        echo -n "Stopping $name ..."
        killproc $name  #这里可以自己写一个kill的命令,但是要能保证杀死所有由这个服务起的进程
        for i in 1 2 3 4 5 6 7 8 9 10
        do
            if ! is_running; then
                break
            fi

            echo -n "."
            sleep 1
        done
        echo

        if is_running; then
            echo "Not stopped; may still be shutting down or shutdown may have failed"
            exit 1
        else
            echo "Stopped"
            if [ -f "$pid_file" ]; then
                rm "$pid_file"
            fi
        fi
    else
        echo "$name not running"
    fi
}

### main logic ###
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status $name  #status这个命令也是/etc/init.d/functions里面的命令,当然你也可以更简单的使用上面的is_runing函数
        ;;
  restart|reload)
        stop
        start
        ;;
  *)
        echo $"Usage: $0 {start|stop|restart|reload|status}"
        exit 1
esac

exit 0

这个脚本的缺点就是使用了. /etc/init.d/functions,这句就相当于source /etc/init.d/functions,因为在systemd和upstart主导的系统中,很可能没有自带/etc/init.d/functions,这个文件中定义了很多内部的shell命令函数,没有这个文件,很多功能函数都得自己去写,或者找替代,比如上面脚本中用到的killproc函数。但是,幸运的是,对于uwsgi程序spawan出来的多进程,只需要杀掉父进程就会把其他进程全部杀掉,所以/etc/init.d/functions中的很多功能函数比如killproc还是可以自己实现的。
对于systemV,如果要将开服务设置成开机自启动,那么就执行chkconfig --add 服务名,这个命令会依据脚本开头设置的chkconfig: 2345 80 20,在/etc/rc.d/rc(2345).d/4个目录下创建S80开头家K20开头的软连接到这个服务在/etc/init.d/下的脚本。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容