systemd使用入门

news2024/9/28 17:45:13

systemd负责管理整个操作系统,功能非常强大。我们在实际工作中,常常使用systemd来管理我们的服务。

(1)想要开机之后自动启动,从而不需要每次开机之后都手动启动进程,可以通过systemd来实现。

(2)如果我们要求进程异常崩溃之后要自动拉起来,可以通过systemd来实现。

(3)我们有3个服务:a、b、c,其中服务b和c的启动依赖于服务a,只有服务a启动之后,服务b和c才可以启动,这样的依赖关系管理,我们也可以通过systemd来实现。

(4)想要限制服务所使用的资源,比如将服务的cpu利用率限制在50%,内存使用限制在1G,我们可以通过systemd来实现。

(5)如果我们想要设置进程的调度策略,那么可以通过systemd来实现。

1最简example

如下是我们自己的代码,在main函数中有一个死循环,在循环中打印一条日志。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main() {
  int i = 0;
  while(1) {
    printf("systemd daemon example\n");
  }
  return 0;
}

service文件,该文件是服务的配置文件,也是systemd可以解析的文件。

[Unit]
Description=hello systemd

[Service]
ExecStart=/home/wangyanlong/systemdtest/daemon

[Install]
WantedBy=multi-user.target

将源码编译成可执行文件:gcc daemon.c -o daemon

将service文件拷贝到systemd的工作目录:cp helloworld.service /lib/systemd/system/

systemd配置文件重新加载:systemctl daemon-reload

启动服务:systemctl start helloworld.service

查看服务状态:ststemctl status helloworld.service

查看日志:joutnalctl -u helloworld.service

2服务类型

systemd中的服务类型,常用的有simple、forking和notify:

2.1simple

最简单的类型,默认的服务类型,上边的例子就是simple类型,当我们的服务本身就会一直运行,那么可以配置simple类型。

2.2forking

forking类型的服务,systemd启动的服务内部会创建子进程,子进程运行之后父进程就退出了。

如下代码,在主进程中会通过fork来执行一个子进程,fork之后,父进程退出。这种情况下,需要配置为forking类型。当父进程退出后,service的状态会切为active状态,父进程退出前,使用systemctl status xxx看到的服务状态为activating。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

int main() {
  printf("fork main\n");
  // sleep(20);

  printf("before fork\n");
  pid_t pid = fork();
  if (pid == 0) {
    execve("/home/wangyanlong/systemdtest/daemon", NULL, NULL);
  }

  sleep(20);
  printf("fork end\n");
  return 0;
}
[Unit]
Description=hello systemd

[Service]
Type=forking
ExecStart=/home/wangyanlong/systemdtest/fork

[Install]
WantedBy=multi-user.target

2.3notify

对于simple和forking类型来说,服务从activating切换为active状态的时机,完全由systemd内部来决定。simple类型,当把服务拉起来之后,便会切换为active状态;forking类型的服务,当主进程退出后,便会切换到active状态。这样的方式,用户不可控,当我们对多个服务有严格的启动顺序要求的时候,这种方式难以满足这样的使用场景,在这种情况下,就需要使用notify。

notify类型的服务,需要用户在代码中调用sd_notify函数来向systemd报状态,systemd收到信息之后则会将服务的状态切换为active状态。

如下代码,在main函数中先睡20s,然后调用sd_notify来通知systemd。通过systemctl status helloworld.service可以看到,启动20s之后,服务的状态切换为active。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <systemd/sd-daemon.h>

int main() {
  sleep(20);
  sd_notify(0, "READY=1");
  int i = 0;
  while(1) {
    printf("systemd daemon example\n");
    // sleep(5);
  }
  return 0;
}

3开机自动重启

使用systemctl enable xxx和systemctl disable xxx可以分别使能开机自启动和禁止开机自启动。

4异常退出自动重启

当服务异常退出时,systemd能够自动将服务重新拉起,这是我们实际工作中经常需要的。同时,当进程正常退出的时候,systemd不会将服务拉起。

如下是进程退出后重启的最简单的例子。Restart配置为always,说明只要进程退出,都会重启,不管进程是正常退出还是异常退出。RestartSec是进程退出之后,间隔多长时间才会重启。

[Unit]
Description=hello systemd

[Service]
Type=simple
ExecStart=/home/wangyanlong/systemdtest/daemon
Restart=always
RestartSec=1

[Install]
WantedBy=multi-user.target

Restart有多个配置:no、always、on-success、on-failure、on-abnormal、on-abort、on-watchdog。其中no是默认值,表示永远不会重启;always是永远会重启,不管进程是正常退出还是异常退出;on-success表示只有进程正常退出的时候才会重启,所谓正常退出,指的是退出码是0,或者被信号SIGHUP、SIGINT、SIGTERM、SIGPIPE或者被中的一个杀死;on-failure表示失败,所谓失败,是当退出码不为0,或者服务是被上述几个信号之外的信号杀死的。

在实际使用中,具体什么退出码是正常的,什么退出码是异常的,我们自己也可以修改,比如我们设置信号SIGKILL为正常的,那么使用SIGKILL杀死进程的时候,也属于正常退出,不会重启。

配置如下:

[Unit]
Description=hello systemd

[Service]
Type=simple
ExecStart=/home/wangyanlong/systemdtest/daemon
Restart=on-failure
RestartSec=1
SuccessExitStatus=SIGKILL

[Install]
WantedBy=multi-user.target

5调度策略

systemd可以设置服务的调度策略和优先级,如下配置,其中CPUSchedulingPolicy=rr和
CPUSchedulingPriority=50分别设置调度策略为RR,优先级是50。

[Unit]
Description=hello systemd

[Service]
Type=simple
ExecStart=/home/wangyanlong/systemdtest/daemon
Restart=on-failure
RestartSec=1
SuccessExitStatus=SIGKILL
CPUSchedulingPolicy=rr
CPUSchedulingPriority=50

[Install]
WantedBy=multi-user.target

6资源限制

使用systemd管理的服务,可以限制服务所使用的资源。systemd通过cgroup来对服务做资源限制,可以限制的资源包括cpu、内存、io等。

如下代码,main函数中是一个while(1)死循环,默认情况下cpu使用率达到100%。但是通过CPUQuota=50%可以将cpu使用限制到50%。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main() {
  while(1) {
  }
  sleep(10);
  return 0;
}

如下配置文件,如果限制了cpu,那么在cgroup下便会创建一个对应的cpu controller,如下图所示,可以看到,在service文件中配置的CPUQuota=50%,在cgroup中对应的参数是cpu.cfs_quota_us,值为50000。

[Unit]
Description=hello systemd

[Service]
Type=simple
ExecStart=/home/wangyanlong/systemdtest/daemon
CPUQuota=50%

[Install]
WantedBy=multi-user.target

7服务之间的依赖

与进程依赖相关的配置有多个After和Before,Requires,Wants。

After、Before的依赖关系最弱,Wants次之,Requires最强。

After和Before可以决定服务启动的顺序,只是约束启动顺序而已,如果在service2.service中配置After=service1.servce,那么即使service1没有启动,service2也是可以启动的。

Wants表示服务之间的依赖关系,假如在service2.service中配置了Wants=service1.servce,如果sevice1没有启动的情况下启动service2,那么会尝试启动service1,不管service1是否能启动,servie2最终都会启动。

Requires是最强的依赖,如果在service2.service中配置了Requires=service1.servce,如果service1启动失败,那么service2也会启动失败,也就是说必须要在service1正常运行的时候,service2才可以正常启动,正常运行。如果service1和service2都在正常运行,这个时候将service1关闭了,那么service2也会被关闭。同样的情况,如果是service2 Wants service1,两个服务都在运行,如果间service1关闭,那么service2还会运行,不会被关闭。

service1.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <systemd/sd-daemon.h>

int main() {
  sleep(20);
  sd_notify(0, "READY=1");
  int i = 0;
  while(1) {
    printf("systemd s1\n");
    // sleep(5);
  }
  return 0;
}

service2.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <systemd/sd-daemon.h>

int main() {
  sleep(20);
  sd_notify(0, "READY=1");
  int i = 0;
  while(1) {
    printf("systemd s2\n");
    // sleep(5);
  }
  return 0;
}

service1.service

[Unit]
Description=service1

[Service]
Type=notify
ExecStart=/home/wangyanlong/systemdtest/service1

[Install]
WantedBy=multi-user.target

service2.service

[Unit]
Description=service2
Wants=service1.service

[Service]
Type=notify
ExecStart=/home/wangyanlong/systemdtest/service2

[Install]
WantedBy=multi-user.target

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2174269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

酒水速送小程序开发制作方案

在餐饮娱乐领域&#xff0c;即时酒水配送服务逐渐成为市场新宠。开发一款集在线选购、快速配送、于一体的酒水配送小程序&#xff0c;以满足用户在家中、聚会场所或商业活动中即时获取各类酒水的需求&#xff0c;提升用户体验&#xff0c;拓宽酒水销售渠道。 目标用户 年轻消费…

JavaScript基础第一天

一、JavaScript简介 JavaScript&#xff08;简称“JS”&#xff09; 是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名的&#xff0c;但是它也被用到了很多非浏览器环境中&#xff0c;JavaScript 基于原型编程、…

如何使用Kimi编写商品管理设计文档:包含流程图和用例图

如何使用Kimi编写商品管理设计文档&#xff1a;包含流程图和用例图 在软件开发项目中&#xff0c;商品管理系统是一个常见的需求。它涉及到商品的添加、编辑、删除、查询以及库存管理等功能。编写商品管理设计文档是确保项目顺利进行的关键步骤。以下是如何使用Kimi编写商品管…

青动CRM-E售后V2.0.4

CRM售后管理系统&#xff0c;旨在助力企业销售售后全流程精细化、数字化管理&#xff0c;主要功能&#xff1a;客户、合同、工单、任务、报价、产品、库存、出纳、收费&#xff0c;适用于&#xff1a;服装鞋帽、化妆品、机械机电、家具装潢、建材行业、快销品、母婴用品、办公用…

Vue 自定义组件实现 v-model 的几种方式

前言 在 Vue 中&#xff0c;v-model 是一个常用的指令&#xff0c;用于实现表单元素和组件之间的双向绑定。当我们使用原生的表单元素时&#xff0c;直接使用 v-model 是很方便的&#xff0c;但是对于自定义组件来说&#xff0c;要实现类似的双向绑定功能就需要一些额外的处理…

【JavaScript】搭建一个具有记忆的简洁个人待办网页

1. HTML 结构 文档类型声明&#xff1a;<!DOCTYPE html>这告诉浏览器这是一个 HTML5 文档。HTML 标签&#xff1a;<html lang"zh-CN">表示整个页面的内容&#xff0c;lang"zh-CN" 表示内容使用简体中文。头部信息&#xff1a;<head><…

RabbitMQ 队列之战:Classic 和 Quorum 的性能洞察

RabbitMQ 是一个功能强大且广泛使用的消息代理&#xff0c;它通过处理消息的传输、存储和交付来促进分布式应用程序之间的通信。作为消息代理&#xff0c;RabbitMQ 充当生产者&#xff08;发送消息的应用程序&#xff09;和使用者&#xff08;接收消息的应用程序&#xff09;之…

速查!2024 CSP-J/S第一轮认证成绩查询及晋级分数线

CSP-J/S 2024第一轮认证成绩已于9月27日13:30开放查询&#xff0c;认证者可登录NOI报名系统&#xff0c;在对应活动内查询个人成绩&#xff0c;CSP-J/S 2024第一轮J组得分为89分及以上的选手、S组得分为56分及以上的选手&#xff0c;可以直接晋级第二轮。 Scratch实验室根据NOI…

大模型微调方法(非常详细),收藏这一篇就够了!

引言 众所周知&#xff0c;大语言模型(LLM)正在飞速发展&#xff0c;各行业都有了自己的大模型。其中&#xff0c;大模型微调技术在此过程中起到了非常关键的作用&#xff0c;它提升了模型的生成效率和适应性&#xff0c;使其能够在多样化的应用场景中发挥更大的价值。 那么&…

数据特征工程:如何计算块熵?| 基于SQL实现

目录 0 信息量定义 1 块熵定义 2 问题描述 ​3 数据准备 4 问题分析 5 小结 0 信息量定义 信息量是指从N 个相等可能事件中选出一个事件所需要的信息度量或含量,也就是在辩识N 个事件中特定的一个事件的过程中所需要提问是或否的最少次数。 在一个系统中,等可能事件的数…

【技术文章】PostgreSQL分区表

引言 PostgreSQL作为一款高度可扩展的企业级关系型数据库管理系统&#xff0c;其内置的分区表功能在处理大规模数据场景中扮演着重要角色。本文将深入探讨PostgreSQL分区表的实现逻辑、详细实验过程&#xff0c;并辅以分区表相关的视图查询、分区表维护及优化案例&#xff0c;…

OpenStack Yoga版安装笔记(十四)启动一个实例

1、官方文档 OpenStack Installation Guidehttps://docs.openstack.org/install-guide/ 本次安装是在Ubuntu 22.04上进行&#xff0c;基本按照OpenStack Installation Guide顺序执行&#xff0c;主要内容包括&#xff1a; 环境安装 &#xff08;已完成&#xff09;OpenStack…

树脂法提纯牛胆汁

牛胆汁中除了含有胆酸外&#xff0c;还含有胆红素、胆固醇、卵磷脂、钠、钾、钙、镁、铁、锌等多种成分。这些成分对人体健康具有一定的益处&#xff0c;如胆红素具有抗氧化作用&#xff0c;卵磷脂有助于降低胆固醇&#xff0c;钠、钾、钙等矿物质对于维持人体正常生理功能也是…

Excel 绝对值怎么求?ABS 函数用法详解

大家好&#xff0c;这里是效率办公指南&#xff01; &#x1f4ca; ABS函数在Excel中用于计算数值的绝对值&#xff0c;这在处理财务、科学和日常办公等领域的数据时非常有用。今天&#xff0c;我们将通过一些具体的日常工作案例&#xff0c;来展示ABS函数的实际应用。 ABS函…

Nginx配置及部署前端项目,安排!

哈喽小伙伴们大家好&#xff01;我是程序媛小李&#xff0c;一位正在往全栈方向发展的前端小姐姐&#xff0c;今天给大家分享一下在日常编码中我们是怎么使用nginx来部署前端项目的&#xff01; Nginx安装 浏览器输入nginx&#xff0c;来到官网 右边找到doewnload&#xff0c…

计算机视觉学习路线:从基础到进阶

计算机视觉学习路线&#xff1a;从基础到进阶 计算机视觉&#xff08;Computer Vision&#xff09;是人工智能和机器学习领域中重要的分支&#xff0c;致力于让计算机能够理解和分析图像、视频等视觉信息。随着深度学习的发展&#xff0c;计算机视觉的应用变得越来越广泛&…

大数据毕业设计选题推荐-广东旅游数据分析系统-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇…

【Kubernetes】常见面试题汇总(四十四)

目录 100.什么是容器资源监视&#xff1f; 101.副本集和复制控制器之间有什么区别&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 69-113 …

笔记整理—linux进程部分(2)使用fork创建进程

为什么要创建进程&#xff0c;首先每个程序的运行都需要一个进程&#xff1b;多进程实现宏观上的并行。 fork的原理&#xff0c;是进程的分裂生长模式。如果操作系统需要一个新的进程&#xff0c;那么就会以cp的方法得到一个新的进程&#xff0c;此时老的进程是父进程&#xff…

springboot实战学习(8)(登录接口中使用“JWT令牌“完成登录认证)(拦截器的创建与注册)

接着上篇博客学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验、也基本完成用户模块的登录接口的主逻辑的基础上。也提到了"JWT令牌"的组成与使用。具体往回看了解的链接如下。springboot实战学习&#xff08;7&#xff09;(JWT令牌的…