linuxcentosservice参数详解
Service⽂件
开门见⼭,直接来看两个实际的服务配置⽂件吧。
第⼀个配置是 CoreOS 系统中 Docker 服务的 Unit ⽂件,路径是 /usr/lib/systemd/system/docker.service,可以看到其中的内容相当精简易读。
[Unit]
Description=Docker Application Container Engine
Documentation=docs.docker
After=docker.socket early-docker.target network.target
Requires=docker.socket early-docker.target
[Service]
Environment=TMPDIR=/var/tmp
Environment=DOCKER_OPTS='--insecure-registry="0.0.0.0/0"'
EnvironmentFile=-/run/v
LimitNOFILE=1048576
LimitNPROC=1048576
ExecStart=/usr/lib/coreos/dockerd --daemon --host=fd:// $DOCKER_OPTS
[Install]
WantedBy=multi-user.target
第⼆个配置的写法风格与前⼀个有所差异,但同样的内容清晰,条理明确。这个配置来⾃ CoreOS 的⼀篇⽂档,作⽤是启动⼀个 Apache 服务容器然后将服务的运⾏信息注册到 Etcd 中。
printformat用法
(注意,这篇⽂档原⽂中的⽰例中似乎有⼀个错误,在启动 docker 时,ExecStart 中的命令参数 -p 80:80 应当为 -p 8081:80,下⾯代码已修正)
[Unit]
Description=My Advanced Service
After=etcd.service
After=docker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache1
ExecStartPre=-/usr/bin/docker rm apache1
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run --name apache1 -p 8081:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStartPost=/usr/bin/etcdctl set /domains/example/10.10.10.123:8081 running
ExecStop=/usr/bin/docker stop apache1
ExecStopPost=/usr/bin/etcdctl rm /domains/example/10.10.10.123:8081
[Install]
WantedBy=multi-user.target
仔细观察着两个服务配置,其中有⼀些很明显的共同点。我们接下来就以这两个 Unit ⽂件为例,⼀步步的分析⼀下 Systemd 服务配置的写法。
Service 的 Unit ⽂件可以分为3个配置区段,其中 Unit 和 Install 段是所有 Unit ⽂件通⽤的,⽤于配置服务(或其他系统资源)的描述、依赖和随系统启动⽅式。⽽ Service 段则是服务类型的 Unit ⽂件(后缀.service)特有的,⽤于定义服务的具体管理和操作⽅法。其他的每种配置⽂件也都会有⼀个特有的配置段,这就是⼏种不同 Unit 配置⽂件最明显的区别。
来看看每个配置段常⽤的参数有哪些。
⼀、Unit 段
Description
⼀段描述这个 Unit ⽂件的⽂字,通常只是简短的⼀句话。
Documentation
指定服务的⽂档,可以是⼀个或多个⽂档的URL路径。
Requires
依赖的其他 Unit 列表,列在其中的 Unit 模块会在这个服务启动的同时被启动,并且如果其中有任意⼀个服务启动失败,这个服务也会被终⽌。
Wants
与 Requires 相似,但只是在被配置的这个 Unit 启动时,触发启动列出的每个 Unit 模块,⽽不去考虑这些模块启动是否成功。
After
与 Requires 相似,但会在后⾯列出的所有模块全部启动完成以后,才会启动当前的服务。
Before
与 After 相反,在启动指定的任⼀个模块之前,都会⾸先确保当前服务已经运⾏。
BindsTo
与 Requires 相似,但是⼀种更强的关联。启动这个服务时会同时启动列出的所有模块,当有模块启动失败时终⽌当前服务。反之,只要列出的模块全部启动以后,也会⾃动启动当前服务。并且这些模块中有任意⼀个出现意外结束或重启,这个服务会跟着终⽌或重启。
PartOf
这是⼀个 BindTo 作⽤的⼦集,仅在列出的任何模块失败或重启时,终⽌或重启当前服务,⽽不会随列出模块的启动⽽启动。
OnFailure
当这个模块启动失败时,就⾃动启动列出的每个模块。
Conflictscentos和ubuntu
与这个模块有冲突的模块,如果列出模块中有已经在运⾏的,这个服务就不能启动,反之亦然。
上⾯这些配置中,除了 Description 外,都能够被添加多次。⽐如前⾯第⼀个例⼦中的After参数在⼀⾏
中使⽤空格分隔指定所有值,也可以像第⼆个例⼦中那样使⽤多个After参数,在每⾏参数中指定⼀个值。
⼆、Install 段
这个段中的配置与 Unit 有⼏分相似,但是这部分配置需要通过 systemctl enable 命令来激活,并且可以通过 systemctl disable 命令禁⽤。另外这部分配置的⽬标模块通常是特定启动级别的 .target ⽂件,⽤来使得服务在系统启动时⾃动运⾏。
WantedBy
和前⾯的 Wants 作⽤相似,只是后⾯列出的不是服务所依赖的模块,⽽是依赖当前服务的模块。
RequiredBy
和前⾯的 Requires 作⽤相似,同样后⾯列出的不是服务所依赖的模块,⽽是依赖当前服务的模块。
Also
当这个服务被 enable/disable 时,将⾃动 enable/disable 后⾯列出的每个模块。
上⾯的两个例⼦中使⽤的都是 “WantedBy=multi-user.target” 表明当系统以多⽤户⽅式(默认的运⾏级别)启动时,这个服务需要被⾃动运⾏。当然还需要 systemctl enable 激活这个服务以后⾃动运⾏才会⽣效。关于 Linux 系统启动时的运⾏级别,可以参看这篇⽂章。
三、Service 段
这个段是 .service ⽂件独有的,也是对于服务配置最重要的部分。这部分的配置选项⾮常多,主要分为服务⽣命周期控制和服务上下⽂配置两个⽅⾯,下⾯是⽐较常⽤到的⼀些参数。
服务⽣命周期控制相关的参数:
Type
服务的类型,常⽤的有 simple(默认类型)和 forking。默认的 simple 类型可以适应于绝⼤多数的场景,因此⼀般可以忽略这个参数的配置。⽽如果服务程序启动后会通过 fork 系统调⽤创建⼦进程,然后关闭应⽤程序本⾝进程的情况,则应该将 Type 的值设置为 forking,否则systemd 将不会跟踪⼦进程的⾏为,⽽认为服务已经退出。
RemainAfterExit
值为 true 或 false(也可以写 yes 或 no),默认为 false。当配置值为 true 时,systemd 只会负责启动服务进程,之后即便服务进程退出了,systemd 仍然会认为这个服务是在运⾏中的。这个配置主要是提供给⼀些并⾮常驻内存,⽽是启动注册后⽴即退出然后等待消息按需启动的特殊类型服务使⽤
ExecStart
这个参数是⼏乎每个 .service ⽂件都会有的,指定服务启动的主要命令,在每个配置⽂件中只能使⽤⼀次。
ExecStartPre
oracle的用户密码认证方式指定在启动执⾏ ExecStart 的命令前的准备⼯作,可以有多个,如前⾯第⼆个例⼦中所⽰,所有命令会按照⽂件中书写的顺序依次被执⾏。
ExecStartPost
指定在启动执⾏ ExecStart 的命令后的收尾⼯作,也可以有多个。
TimeoutStartSec
启动服务时的等待的秒数,如果超过这个时间服务任然没有执⾏完所有的启动命令,则 systemd 会认为服务⾃动失败。这⼀配置对于使⽤Docker 容器托管的应⽤⼗分重要,由于 Docker 第⼀次运⾏时可以能会需要从⽹络下载服务的镜像⽂件,因此造成⽐较严重的延时,容易被systemd 误判为启动失败⽽杀死。通常对于这种服务,需要将 TimeoutStartSec 的值指定为 0,从⽽关闭超时检测,如前⾯的第⼆个例⼦。ExecStop
停⽌服务所需要执⾏的主要命令。
ExecStopPost
指定在 ExecStop 命令执⾏后的收尾⼯作,也可以有多个。
TimeoutStopSec
停⽌服务时的等待的秒数,如果超过这个时间服务仍然没有停⽌,systemd 会使⽤ SIGKILL 信号强⾏杀死服务的进程。
Restart
这个值⽤于指定在什么情况下需要重启服务进程。常⽤的值有 no,on-success,on-failure,on-abnor
mal,on-abort 和 always。默认值为no,即不会⾃动重启服务。这些不同的值分别表⽰了在哪些情况下,服务会被重新启动,参见下表。
服务退出原因
no
always
on-failure
on-abnormal
on-abort
no-success
正常退出
异常退出
启动/停⽌超时
老师评语null什么意思
被异常KILL
RestartSec
如果服务需要被重启,这个参数的值为服务被重启前的等待秒数。
ExecReload
重新加载服务所需执⾏的主要命令。
服务上下⽂配置相关的参数:
Environment
为服务添加环境变量,如前⾯的第⼀个例⼦中所⽰。
EnvironmentFile
指定加载⼀个包含服务所需的环境变量列表的⽂件,⽂件中的每⼀⾏都是⼀个环境变量的定义。
Nice
服务的进程优先级,值越⼩优先级越⾼,默认为0。-20为最⾼优先级,19为最低优先级。
WorkingDirectory
指定服务的⼯作⽬录。
RootDirectory
指定服务进程的根⽬录( / ⽬录),如果配置了这个参数后,服务将⽆法访问指定⽬录以外的任何⽂件。
User
指定运⾏服务的⽤户,会影响服务对本地⽂件系统的访问权限。
Group
指定运⾏服务的⽤户组,会影响服务对本地⽂件系统的访问权限。
LimitCPU / LimitSTACK / LimitNOFILE / LimitNPROC 等
限制特定服务可⽤的系统资源量,例如 CPU,程序堆栈,⽂件句柄数量,⼦进程数量… 不再展开说明了,值的含义可参考 Linux ⽂档资源配额部分中 RLIMIT_ 开头的那些参数们。
列完这么⼀⼤推参数的我也是醉了(这些都是常⽤的参数,不常⽤的还没写咧),但其实嘛,Systemd 的精华也就在此了。再仔细⼀推敲,这么些冗长的参数之间还是有些规律的,并且⼤多可以望⽂⽣义,因此写 Unit ⽂件的差事本⾝倒并不让⼈觉得枯燥。反观过去需要学习N种不同配置格式来管理N种不同的系统资源的⽅法,Systemd的理念实在是先进了太多了。⽽这些参数云云,⼤概只有⽤得多了,才会觉得它们看起来不那么讨厌了吧o(//_//)o
Fleet 的 X-Fleet 段
前⾯讨论的都是 Systemd 使⽤的 Unit ⽂件。在这个系列的 Fleet 那篇中,演⽰了 Fleet 中的服务配置。
Fleet 的 Unit 服务描述⽂件,实际上就是 Systemd 的 .service 配置⽂件的翻版。但为了⽅便服务在集环境的⾃适应管理,Fleet 在Systemd 的 Unit 配置基础上添加了⼀个 X-Fleet 段,专门⽤于描述服务应该被分配到集的哪些节点启动。它的可⽤参数只有5个,可以请出来⼀⼀亮相。
MachineID
直接了当的告诉 Fleet 这个服务只能运⾏在特定的⼀个节点上,注意这⾥的值必须是完整的节点 ID,这个 ID 可以通过 “fleetctl list-machines -l” 命令获得。
MachineOf
值是另⼀个 .service ⽂件,表⽰当前服务必须运⾏在与指定的这个服务在同⼀个节点上。
MachineMetadata
值是⼀个节点的 Metadata 内容,例如 "region=us-east-1" 。这些 Metadata 是在启动节点时通过 Cloudinit 写进去的,具体⽅法在系列的Fleet 那篇⽂章有提及。这个参数可以使⽤多次,或在通过空格分隔将多个值同时传进去。
Conflicts
值是⼀个 .service ⽂件的,Conflicts参数也可以使⽤多次,并且其值可以使⽤通配符,例如 apache* 表⽰所有以 “apache” 开头的服务。
Global
vs2017全称
如果值为 true,则这个服务会被部署到集中符合 MachineMetadata限定条件的每⼀个节点上。注意,当 Global 值为 true 时,除了MachineMetadata外的所有其他约束条件都会被忽略。
前四个参数在 Fleet v0.8 版本前被命名为 X-ConditionMachineID、X-ConditionMachineOf、X-ConditionMachineMetadata和 X-Conflicts,这些写法现在已经停⽌使⽤了,但仍然可能会在⼀些早期的⽂档或⽹络⽂章中出现,如果看见了,淡定的飘过吧。
Unit模板
在现实中,往往有⼀些应⽤需要被复制多份运⾏,例如在⼀个负载均衡实例后⾯运⾏的多个相同的服务实例。但是按照之前的例⼦,每个服务都需要⼀个单独的 Unit ⽂件,这样复制多份相同⽂件的做显然不便于服务的管理。为此 Systemd 定义了⼀种特殊的 Service Unit⽂件,称为 Unit 模板。
模板⽂件的主要特点是,⽂件名以@符号结尾,⽽启动的时候指定的Unit名称为模板名称附加⼀个参数字符串。例如,将之前的例⼦第⼆个Unit ⽂件修改为可以⽤于启动多个实例的模板。
⼀、⾸先修改⽂件名,添加⼀个@符号
例如原来的⽂件名是 apache.service,那么可以将它修改为 apache@.service,这样做的⽬的是表⾯这个⽂件是⼀个模板⽂件。⽽在服务启动时可以在@后⾯放置⼀个⽤于区分服务实例的附加字符串参
数,通常这个参数会使⽤监听的端⼝号或使⽤的控制台TTY编号等。例如“systemctl start apache@8080.service”。
⼆、然后修改 Unit ⽂件内容
Unit ⽂件中可以获取服务启动时的附加参数,因此通常需要修改 Unit ⽂件中不应固定的部分,例如服务监听的 IP 和端⼝,替换为从附加参数中获取。
[Unit]
Description=My Advanced Service Template
After=etcd.servicedocker.service
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill apache%i
ExecStartPre=-/usr/bin/docker rm apache%i
ExecStartPre=/usr/bin/docker pull coreos/apache
ExecStart=/usr/bin/docker run --name apache%i -p %i:80 coreos/apache /usr/sbin/apache2ctl -D FOREGROUND
ExecStartPost=/usr/bin/etcdctl set /domains/example/%H:%i running
ExecStop=/usr/bin/docker stop apache1
ExecStopPost=/usr/bin/etcdctl rm /domains/example/%H:%i
[Install]
WantedBy=multi-user.target
仔细观察⼀下变化了的地⽅,上⾯使⽤到了占位符 %H 和 %i,常⽤的占位符有6种(⼀共19种,其余不怎么常⽤的查⽂档吧),这些占位符会在 Unit 启动时被实际的值动态的替换掉。
占位符
作⽤
%n
完整的 Unit ⽂件名字,包括 .service 后缀名
%m
实际运⾏的节点的 Machine ID,适合⽤来做Etcd路径的⼀部分,例如 /machines/%m/units
%b
作⽤有点像 Machine ID,但这个值每次节点重启都会改变,称为 Boot ID
%H
实际运⾏节点的主机名
%p
Unit ⽂件名中在 @ 符号之前的部分,不包括 @ 符号
%i
Unit ⽂件名中在 @ 符号之后的部分,不包括 @ 符号和 .service 后缀名
顺带⼀提,这些参数中除了 %i 以外,同样可以⽤于⾮模板的 Unit ⽂件中。%p 在普通 Unit ⽂件中会被动态替换为服务名称去掉 .service 后缀的名字。
三、启动 Unit 模板的服务实例
模板服务的启动对于 Systemd 和 Fleet ⼤致相同。
Systemd 的情况略简单⼀些,只需要运⾏时加上后缀参数。例如 “systemctl start apache@8080.service”。Systemd ⾸先会在其特定的⽬录下寻名为 apache@8080.service的⽂件,如果没有到,⽽⽂件名中包含@字符,它就会尝试去掉后缀参数匹配模板⽂件。例如没有到apache@8080.service,那么Systemd会到apache@.service,并将它通过模板⽂件中实例化。
Fleet 没有特定的 Unit ⽂件存放⽬录,不过在通过 fleetctl start 或 fleetctl submit 命令指定 Unit ⽂件路径时加上后缀参数,Fleet 同样会⾃动匹配去掉后缀参数后的模板⽂件。例如 “fleetctl submit ${HOME}/apache@8080.service”,就会匹配到 ${HOME} ⽬录下⾯的
apache@.service 模板⽂件。
后续综合案例的⽂章中,还会结合实际例⼦详细的介绍模板的使⽤场景。
linux清空命令行
⼩结
这⼀篇的内容略为零碎,主要是对 CoreOS 中的系统资源和服务起着管理作⽤的 Unit 配置⽂件做了⽐较深⼊的说明。特别是最后的 Unit 模板部分在⼀定程度上赋予了服务横向拓展的能⼒,在实际的项⽬环境中使⽤得相当普遍。这些系统管理⽅⾯的技巧,需要⼀定的实战磨练才能体会其中的好处。
最近有同事问我,介绍了这么多的 CoreOS,能否⽤⼀句话来评述⼀下这个系统,以及它最适⽤于什么样的应⽤场景呢?
对于第⼀个问题,CoreOS 并不是什么神秘的银弹,它只是⼀个“理念⽐较先进(具体见系列第⼀篇)”并且“对集和应⽤容器⽐较友好”的服务器 Linux 发⾏版。有些⼈会追问,要是把 CoreOS 和其他发⾏版进⾏对⽐哪个好⽤呢。这个…专注的领域不⼀样啊,CoreOS 永远也不会替代 Fedora 和 Ubuntu 这些桌⾯ Linux 发⾏版的地位,因为它实际上是⼀个⾼度精简的没有 GUI 和 x-window 的操作系统(但并不是说CoreOS 不能够提供需要 GUI 的服务,因为可以在容器中安装 x-window 和 VNC 服务)。
对于第⼆个问题,其实是没有准确答案的,Linux 系统发⾏版的选择完全是个⼈偏好问题。普遍来说,基于 CoreOS 的⾃动⽆缝升级和对容器和集友好的特性,它会⽐较适⽤于需要长期运⾏,并且具备横向扩展架构,特别是 Micro Service 架构的以对外提供服务为⽬的的集。但并不是说 CoreOS 就
不能⽤在⼀般的服务器场景,美国的SaaS云服务⽹站Iron.io和购物⽹站Shopify都使⽤了CoreOS 作为其业务⽀撑的平台,它们的业务场景除了都使⽤⼤规模的集外,各⽅⾯都很不⼀样。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。