Ubuntu开机自启服务systemd.service配置教程(Ubuntu服务)(Linux服务)upstart
文章目录
- 为什么要将程序配置成服务?
- 1. 自动启动
- 2. 后台运行
- 3. 定时重启
- 4. 简化管理
- 5. 整合系统
- 版本支持
- 1. Ubuntu 14.04及更早版本:使用`upstart`作为默认的init系统
- /etc/rc.local
- 旧版本
- 新版本
- 2. Ubuntu 15.04到16.04版本:默认使用`systemd`作为init系统,但仍然兼容`upstart`
- 3. Ubuntu 16.10及更高版本:默认使用`systemd`作为init系统
- 总结
- 开机自启服务原理
- 配置步骤
- 1. 创建配置文件
- 2. 编辑配置文件
- 3. 拷贝配置文件
- 4. 启用服务
- 5. 启动服务
- 6. 停止服务
- 7. 禁用服务
- 配置项解释
- 配置父项
- 配置子项
- `[Unit]`配置子项
- - `Description`:用于设置服务的描述信息。
- - `Requires`:用于指定服务所依赖的其他服务。
- - `After`:用于指定服务启动的顺序,可以设置在哪些服务之后启动。
- - `Before`:用于指定服务启动的顺序,可以设置在哪些服务之前启动。
- `[Service]`配置子项
- - `ExecStart`:用于指定服务的启动命令。
- - `WorkingDirectory`:用于指定服务的工作目录。
- - `Environment`:用于设置服务的环境变量。
- - `User`:用于指定服务运行的用户。
- - `Group`:用于指定服务运行的用户组。
- `[Install]`配置子项
- - `WantedBy`:用于指定服务在哪些目标(target)下启动。
- - `RequiredBy`:用于指定哪些目标(target)依赖于该服务。
- systemd官方文档(systemd.service完整配置选项)
- systemd支持在/etc/systemd/system创建子目录,便于我们方便管理我们的.service文件
- vscode相关插件:Systemd Helper
- 使用软链接链接systemd配置文件
为什么要将程序配置成服务?
我们在linux系统下启动一个程序,一般用一条命令,或者执行一个脚本就行了,那么,为什么还要将程序配置成服务?这样做有什么好处?
1. 自动启动
配置成服务后,程序将在系统启动时自动启动,无需手动操作。这样可以确保程序在系统重启后能够自动运行,避免因为人为疏忽或其他原因导致程序未能启动。
2. 后台运行
配置成服务后,程序将以后台进程的方式运行,不会占用终端或用户会话。这样可以确保程序在后台持续运行,即使用户注销或关闭终端。
3. 定时重启
通过配置服务,可以设置服务在异常退出时自动重启。这样可以提高程序的稳定性,确保在出现问题时能够及时恢复运行。
4. 简化管理
配置成服务后,可以使用系统工具(如systemctl
)来管理服务,如启动、停止、重启、查看状态等。这样可以方便地管理和监控程序的运行状态。
5. 整合系统
配置成服务后,程序可以与系统的其他服务和组件进行整合。例如,可以设置服务的依赖关系,确保在其他服务启动之前先启动该服务;还可以将服务与日志记录、监控系统等集成,方便管理和故障排查。
版本支持
在不同的Ubuntu版本中,配置开机自启服务的方式可能会有所不同。以下是几个常见的Ubuntu版本和它们支持的开机自启服务类型。本文主要讲解Ubuntu 16.10及更高版本,使用systemd
作为init系统的服务开机自启方式。
1. Ubuntu 14.04及更早版本:使用upstart
作为默认的init系统
可以创建一个.conf
文件来配置开机自启服务,然后将它放在/etc/init/
目录下。
/etc/rc.local
旧版本
rc.local
是一种在Ubuntu中配置开机自启服务的方式,它属于早期版本的init系统。具体来说,rc.local
是在Ubuntu 14.04及更早版本中使用的方式,使用的是upstart
作为默认的init系统。
rc.local
是一个脚本文件,位于/etc/rc.local
。你可以在该文件中添加要在系统启动时执行的命令或脚本。这些命令或脚本将在系统启动时自动执行。
以下是使用rc.local
配置开机自启服务的步骤:
-
打开
rc.local
文件:sudo nano /etc/rc.local
-
在文件中添加你要执行的命令或脚本。例如,如果要启动一个名为
my_service
的服务,可以添加以下内容:/path/to/your/service
注意,命令或脚本必须是可执行的。
-
保存并关闭文件。
-
确保
rc.local
文件具有可执行权限:sudo chmod +x /etc/rc.local
-
重启系统,服务将在系统启动时自动执行。
需要注意的是,rc.local
方式在较新的Ubuntu版本中已经不再推荐使用,因为它是基于旧的upstart
系统。对于使用systemd
作为init系统的较新版本的Ubuntu,建议使用systemd
的方式来配置开机自启服务。
新版本
在一些较新的Ubuntu版本中,如Ubuntu 16.04及更高版本,rc.local
文件默认是被禁用的,因为这些版本使用systemd
作为默认的init系统。systemd
不会自动执行rc.local
文件中的内容。
为了在这些版本中使用rc.local
文件,可以通过配置rc-local.service
来实现。rc-local.service
是一个systemd
服务单元,用于在系统启动时执行rc.local
文件中的内容。
以下是配置rc-local.service
的步骤:
-
创建
rc-local.service
文件:sudo nano /etc/systemd/system/rc-local.service
-
在文件中添加以下内容:
[Unit] Description=/etc/rc.local Compatibility ConditionPathExists=/etc/rc.local[Service] ExecStart=/etc/rc.local start Type=forking TimeoutSec=0 RemainAfterExit=yes[Install] WantedBy=multi-user.target
-
创建
rc.local
文件:sudo nano /etc/rc.local
-
在
rc.local
文件中添加要执行的命令或脚本。 -
保存并关闭文件。
-
设置
rc.local
文件的权限:sudo chmod +x /etc/rc.local
-
启用
rc-local.service
:sudo systemctl enable rc-local.service
-
启动
rc-local.service
:sudo systemctl start rc-local.service
rc.local
文件中的内容将在系统启动时自动执行。
对于较新的Ubuntu版本,使用rc.local
和rc-local.service
的方式可能不是最佳实践。推荐使用systemd
的方式来配置开机自启服务,以便与当前的init系统保持一致。
2. Ubuntu 15.04到16.04版本:默认使用systemd
作为init系统,但仍然兼容upstart
可以使用upstart
的方式来配置开机自启服务,或者使用systemd
的方式。
3. Ubuntu 16.10及更高版本:默认使用systemd
作为init系统
可以使用systemd
的方式来配置开机自启服务。
总结
systemd
是目前主流的init系统,大多数Ubuntu版本都支持使用systemd
来配置开机自启服务。但是,对于旧版本的Ubuntu,可能需要使用upstart
来配置开机自启服务。
开机自启服务原理
以使用systemd作为系统初始化的管理器为例。systemd是一个Linux系统和服务管理器,它负责启动、停止和管理系统中的各种服务。
当系统启动时,systemd会读取/etc/systemd/system/
目录下的服务配置文件,并根据配置文件中的指令来启动相应的服务。配置文件中的ExecStart
字段指定了要执行的命令或脚本,WorkingDirectory
字段指定了命令或脚本的工作目录。
通过使用systemctl enable
命令,我们告诉systemd将该服务配置文件链接到系统的默认目标(default target),使得该服务在系统启动时自动启动。
当系统启动时,systemd会按照配置文件中的指令来启动服务。如果服务成功启动,systemd会将服务的状态标记为"active"。如果服务启动失败,systemd会将服务的状态标记为"failed"。
通过使用systemctl start
命令,我们可以手动启动服务。而使用systemctl stop
命令可以停止服务。
通过使用systemctl disable
命令,我们可以禁用服务,使得该服务在系统启动时不会自动启动。
总结:使用systemd来管理服务的启动和停止,通过配置服务配置文件并将其链接到系统的默认目标,使得服务在系统启动时自动启动。
配置步骤
以systemd
作为init系统的服务开机自启方式为例。下面是配置开机自启服务的步骤:
1. 创建配置文件
创建一个服务配置文件,以.service
为后缀,比如my_service.service
。
2. 编辑配置文件
使用文本编辑器打开该文件,并添加以下内容:
[Unit]
Description=My Service
After=network.target[Service]
ExecStart=/path/to/your/script.sh
WorkingDirectory=/path/to/your/working/directory[Install]
WantedBy=default.target
在上面的配置中,需要替换/path/to/your/script.sh
为你要在开机时运行的脚本的路径,/path/to/your/working/directory
为脚本的工作目录。
3. 拷贝配置文件
将该服务配置文件移动到/etc/systemd/system/
目录下:
sudo mv my_service.service /etc/systemd/system/
4. 启用服务
使用以下命令启用服务:
sudo systemctl enable my_service
5. 启动服务
使用以下命令启动服务:
sudo systemctl start my_service
现在,该服务将会在每次开机时自动启动。
6. 停止服务
如果需要停止服务,可以使用以下命令:
sudo systemctl stop my_service
7. 禁用服务
如果需要禁用服务,可以使用以下命令:
sudo systemctl disable my_service
配置项解释
配置父项
在systemd中,配置文件通常使用.service
扩展名,并且使用INI格式
。一个.service
文件可以包含以下三个配置项:
-
[Unit]
:这个配置项定义了服务的基本属性,如服务的描述、依赖关系、启动顺序等。在这个配置项中,可以设置服务的名称、描述、依赖关系、启动顺序等。 -
[Service]
:这个配置项定义了服务的具体执行方式,如服务的启动命令、环境变量、工作目录等。在这个配置项中,可以设置服务的启动命令、环境变量、工作目录等。 -
[Install]
:这个配置项定义了服务的安装方式,如服务的启动级别、启动顺序等。在这个配置项中,可以设置服务的启动级别、启动顺序等。
这三个配置项分别定义了服务的基本属性、具体执行方式和安装方式。
除了[Unit]
、[Service]
和[Install]
之外,systemd还支持其他一些配置项,用于进一步定义和配置服务。以下是一些常用的配置项:
-
[Path]
:用于监控文件或目录的变化,并在变化发生时触发服务的启动、停止或重启。 -
[Timer]
:用于定义定时器,可以在指定的时间间隔或特定时间点触发服务的启动、停止或重启。 -
[Socket]
:用于定义套接字,可以监听指定的网络端口或UNIX域套接字,并在有连接请求时触发服务的启动。 -
[Mount]
:用于定义挂载点,可以在指定的文件系统挂载或卸载时触发服务的启动、停止或重启。 -
[Automount]
:用于定义自动挂载点,可以在访问指定的文件系统路径时自动挂载该文件系统。 -
[Swap]
:用于定义交换空间,可以在指定的交换文件或分区被启用或禁用时触发服务的启动、停止或重启。
配置子项
[Unit]
配置子项
- Description
:用于设置服务的描述信息。
- Requires
:用于指定服务所依赖的其他服务。
- After
:用于指定服务启动的顺序,可以设置在哪些服务之后启动。
- Before
:用于指定服务启动的顺序,可以设置在哪些服务之前启动。
[Service]
配置子项
- ExecStart
:用于指定服务的启动命令。
- WorkingDirectory
:用于指定服务的工作目录。
- Environment
:用于设置服务的环境变量。
- User
:用于指定服务运行的用户。
- Group
:用于指定服务运行的用户组。
[Install]
配置子项
- WantedBy
:用于指定服务在哪些目标(target)下启动。
WantedBy
是systemd服务配置文件中的一个选项,用于指定服务所属的启动级别(target)。启动级别是一组定义了系统启动过程中要启动的服务的目标单元的集合。
在systemd中,启动级别由target单元来表示。每个target单元都是一组相关的服务单元的集合,用于定义系统在不同阶段启动时应该启动哪些服务。例如,multi-user.target
是一个常见的启动级别,用于表示系统已经启动到多用户模式,此时应该启动所有与用户交互相关的服务。
WantedBy
选项用于指定服务所属的启动级别。它接受一个目标单元的名称作为参数。当你将服务配置文件放置在/etc/systemd/system/
目录下,并使用systemctl enable
命令启用服务时,systemd会根据WantedBy
选项中指定的目标单元,将服务添加到相应的启动级别中。
在上面的例子中,WantedBy=multi-user.target
表示该服务应该属于multi-user.target
启动级别,即系统已经启动到多用户模式时应该启动该服务。
在systemd中,有以下几个常见的启动级别(target):
poweroff.target
:系统关机时的目标单元。rescue.target
:用于系统救援的目标单元,提供了一个最小的功能集合,用于修复系统问题。multi-user.target
:多用户模式的目标单元,用于正常的多用户操作。graphical.target
:图形界面模式的目标单元,用于启动图形界面环境。reboot.target
:系统重启时的目标单元。
除了上述常见的启动级别,还有其他一些特定的启动级别,如network.target
(网络启动完成后的目标单元)、default.target
(默认目标单元,通常是multi-user.target
或graphical.target
)等。
对于普通程序来说,通常会将其配置为属于multi-user.target
或graphical.target
这样的启动级别,以便在系统启动到多用户模式或图形界面模式时自动启动。你可以根据你的需求选择适合的启动级别。
- RequiredBy
:用于指定哪些目标(target)依赖于该服务。
systemd官方文档(systemd.service完整配置选项)
https://www.freedesktop.org/software/systemd/man/systemd.service.html
systemd支持在/etc/systemd/system创建子目录,便于我们方便管理我们的.service文件
systemd会递归遍历/etc/systemd/system
目录下的所有.service
文件以及子目录中的.service
文件。这意味着可以在/etc/systemd/system
目录下创建子目录,并在子目录中放置您的服务配置文件。
例如,如果在/etc/systemd/system
目录下创建了一个名为my-service
的子目录,并将服务配置文件my-service.service
放置在该子目录中,systemd仍然能够找到并管理该服务。
这种递归遍历的机制使得您可以更好地组织和管理多个服务的配置文件,而不会造成混乱。
vscode相关插件:Systemd Helper
可以方便我们编辑systemd配置文件:
使用软链接链接systemd配置文件
可以将.service
文件创建为软链接,链接到实际文件。这样做可以使服务配置文件保持在原始位置,同时在/etc/systemd/system
目录下创建一个链接,以便systemd能够找到并管理该服务。
以下是创建软链接的步骤:
-
在
/etc/systemd/system
目录下创建一个软链接,链接到实际文件。例如,假设实际文件位于/path/to/my-service/my-service.service
,可以使用以下命令创建软链接:sudo ln -s /path/to/my-service/my-service.service /etc/systemd/system/
-
确保软链接的文件权限正确设置。一般来说,软链接的所有者应为
root
用户,权限应为644
:sudo chown root:root /etc/systemd/system/my-service.service sudo chmod 644 /etc/systemd/system/my-service.service
通过这种方式,服务配置文件将保持在原始位置,而软链接将位于/etc/systemd/system
目录下,使systemd能够找到并管理该服务。这样做的好处是,当需要修改或更新服务配置文件时,只需在原始位置进行操作,而不需要修改软链接。
相关文章:

Ubuntu开机自启服务systemd.service配置教程(Ubuntu服务)(Linux服务)upstart
文章目录 为什么要将程序配置成服务?1. 自动启动2. 后台运行3. 定时重启4. 简化管理5. 整合系统 版本支持1. Ubuntu 14.04及更早版本:使用upstart作为默认的init系统/etc/rc.local旧版本新版本 2. Ubuntu 15.04到16.04版本:默认使用systemd作…...

大数据课程E4——Flume的Channel
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Channel的作用和配置; ⚪ 掌握Channel的使用方法; ⚪ 掌握Channel的File Channel; ⚪ 掌握Channel的JDBC Channel; ⚪ 掌握Channel的Spillable Memory Channel; 一、Memory Ch…...

es6中的Map和Set数据结构
Map Map对象可以用于保存键值对 1.创建 一个Map对象 const map new Map() 2.Map的一些方法 set(key,value):通过键值对向Map对象中添加元素get(key):通过建拿到对应的值size:返回Map对象中所包含的键值对的个数has(key):判断Map对象中是否有对应的key,返回一个…...

MyBatis 框架基本的增删改查
提示:写代码要严谨 文章目录 前言前期准备MyBatis CRUD操作流程增加功能删除功能修改功能查询功能#{} 占位符${} 占位符两种占位符的区别❗ 映射文件总结❗ mapper 代理方式实现CRUDmapper代理开发规范增加功能删除功能修改功能查询功能 前言 提示:myba…...

Javascript--JSON
什么是 JSON? JavaScript中的JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于存储和表示结构化的数据。JSON使用键值对的方式组织数据,并支持基本数据类型(字符串、数字、布尔值、数组和对象&…...

Rust: error: failed to run custom build command for `openssl-sys v0.9.71`
error: failed to run custom build command for openssl-sys v0.9.71 解决 windows : openssl 不要选Light版 设置环境变量 cmd: set OPENSSL_DIR“C:\Program Files\OpenSSL-Win64” OPENSSL_DIR:C:\Program Files\OpenSSL-Win64 linux:…...

Excel修改日期格式,改变日期的筛选方式
我们有两列日期数据: 左边这一列筛选会显示: 右边这一列筛选会显示: 修改格式,将【日期1】改为【日期2】 将【日期1】的格式修改为文本格式即可 修改格式,将【日期2】改为【日期1】 选中日期2,点击【数据…...

【RabbitMQ(day2)】默认(直连)交换机的应用
文章目录 一、第一种模型(Hello World)二、第二种模型(work queue)自动确认机制的后果和公平分配 三、阐述默认交换机 这篇博客是以下资料学后的总结: 不良人的RabbitMQ的教学视频 官方启动教程 RabbitMQ中文文档 一、…...

谷粒商城第八天-商品服务之品牌管理的整体实现(直接使用逆向生成的代码;含oss文件上传)
目录 一、总述 二、前端部分 2.1 创建好品牌管理菜单 2.2 复制组件 编辑2.3 复制api 编辑 2.4 查看效果 编辑2.5 需要优化的地方 2.6 具体优化实现 2.6.1 优化一:将表格的状态列(这里是是否显示列)修改为开关ÿ…...

阿里云率先荣获容器集群稳定性先进级认证
7 月 25 日,由中国信通院发起的“2023 稳保体系”评估结果在可信云大会现场公布,阿里云容器服务 ACK 成为首批通过“云服务稳定运行能力-容器集群稳定性”评估的产品,并荣获“先进级”认证。 云原生技术正在激活应用构建新范式,构…...

【SpringBoot笔记37】SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket
这篇文章,主要介绍SpringBoot基于@ServerEndpoint、@OnMessage等注解的方式集成WebSocket。 目录 一、基于注解集成WebSocket 1.1、WebSocket常见注解 1.2、创建WebSocket服务端 1.3、配置ServerEndpointExpor...

PyTorch(安装及卸载)
目录 1. 安装 2. 卸载 参考文献 为什么用PyTorch:简单来说,19年之前tensorflow是大哥,19年tensorflow和PyTorch双龙并行,20年之后PyTorch一往无前。宗旨,哪个用的人多用哪个。 1. 安装 1. 先打开Anaconda Prompt&…...

webScoket
webScoket是什么? 支持端对端通讯可以由客户端发起,也可以有服务端发起用于消息通知、直播间讨论区、聊天室、协同编辑等 做一个简单的webScoket 客户端配置: 1、新建一个页面叫web-scoket.html <!DOCTYPE html> <html lang"…...

【C语言初阶(20)】调试练习题
文章目录 前言实例1实例2 前言 在我们开始调试之前,应该有个明确的思路;程序是如何完成工作的、变量到达某个步骤时的值应该是什么、出现的问题大概会在什么位置。这些东西在调试之前都需要先确认下来,不然自己都不知道自己在调试个什么东西…...

MicroPython ESP32网页实时更新DHT11数据显示
MicroPython ESP32网页实时更新DHT11数据显示 📌相关篇《MicroPython ESP32 读取DHT11温湿度传感器数据》📍《【Micropython esp32/8266】网页点灯控制示例》 ✨本例综合以上两篇文章内容实现:在本地网页中显示DHT11温度传感器数据。可以做到…...

JavaWeb之HTML基础篇(一)
系列文章目录 HTML基础篇(一) 文章目录 系列文章目录HTML基础篇(一)[TOC](文章目录) 前言一、HTML简介1.1介绍1.2HTML文件的书写规范1.3 HTML标签介绍1.4 HTML常见的标签 二、CSS的简介2.1css技术介绍2.2 CSS与HTML结合的三种方式…...

TVM_深度学习编译器
TVM_深度学习编译器 TVM所做的是要比传统compiler更偏上层的,你可以把它理解成source-to-source compiler,需要其他的后端(backend)来生成最后的指令。比如当编译的Target是Intel CPU时,翻译的顺序是Relay IR -> TVM IR/ Halide IR -> LLVM IR,之后交给LLVM生成最后…...

Flutter InheritedWidget 共享状态管理
InheritedWidget和React中的context功能类似,可以实现跨组件数据的传递。 定义一个共享数据的InheritedWidget,需要继承自InheritedWidget 这里定义了一个of方法,该方法通过context开始去查找祖先的HYDataWidget(可以查看源码查找…...

什么是反射?Java反射?反射的优缺点
目录 什么是反射(Reflection )?Java反射?反射的优缺点获取Class对象的三种方式:java反射技术的应用场景 什么是反射(Reflection )? 主要是指程序可以访问、检测和修改它本身状态或行…...

小红书2020校招测试开发后端笔试题卷三
//完全背包求组合数 #include <iostream> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; int value[300]; // vector<int>vis; // vector<int>vis1; map<vector<int>,int>m…...

python数据可视化Matplotlib
1.绘制简单的折线图 # -*- coding: utf-8 -*- import matplotlib.pyplot as pltinput_values [1, 2, 3, 4, 5] squares [1, 4, 9, 16, 25] plt.style.use(seaborn) fig, ax plt.subplots() ax.plot(input_values, squares, linewidth3) # 线条粗细# 设置图表标题并给坐标…...

firewalld防火墙
firewalld防火墙 它属于包过滤防火墙。工作在网络层,是centos7自带的默认防火墙。主要是取代iptables。 firewalld的两种配置模式: 分别是运行时配置和永久配置。 iptable是静态防火墙 firewalld是动态防火墙 它是按照区域来划分的,有9…...

iMacros WebBrowser Component for .NET
iMacros WebBrowser Component for .NET 在几分钟内实现应用程序自动化 快速轻松地将iMacro集成到您的应用程序中。不需要单独的安装程序。 无缝集成 iMacros与您的.NET应用程序无缝集成,作为Microsoft WebBrowser控件的替代品。它甚至可以用作每个.NET应用程序中的…...

3,堆,桶排序,排序总结【p4-p5】
桶排序,排序总结 3.1堆3.1.1堆结构3.1.1.1完全二叉树3.1.1.2堆分为大根堆和小根堆3.1.1.2.1案例1-去掉最大数字,使剩下的数字依然是大根堆3.1.1.2.2案例23.1.1.2.3案例33.1.1.2.4案例4-方便制造大根堆方法 3.1.2堆排序3.1.2.1案例-堆排序的扩展3.1.2.1.1…...

使用langchain与你自己的数据对话(四):问答(question answering)
之前我已经完成了使用langchain与你自己的数据对话的前三篇博客,还没有阅读这三篇博客的朋友可以先阅读一下: 使用langchain与你自己的数据对话(一):文档加载与切割使用langchain与你自己的数据对话(二):向量存储与嵌入使用langc…...

如何快速开拓海外华人市场?附解决方案!
开拓华人市场对于企业来说是非常必要的。华人市场庞大且潜力巨大,拥有巨额的消费能力。随着华人经济的不断增长,越来越多的企业开始意识到华人市场的重要性。 通过开拓华人市场,企业可以获得更多的销售机会,并且在竞争激烈的市场…...

【云原生-制品管理】制品管理的优势
制品介绍制品管理-DevOps制品管理优势总结 制品介绍 制品管理指的是存储、版本控制和跟踪在软件开发过程中产生的二进制文件或“制品”的过程。这些制品可以包括编译后的源代码、库和文档,包括操作包、NPM 和 Maven 包(或像 Docker 这样的容器镜像&…...

Java爬虫----HttpClient方式(获取数据篇)
目录 一、爬虫的定义 二、获取数据 (1)基于Get方式的请求(无参) (2)基于Get方式请求(有参) (3)基于Post方式的请求(无参) &…...

计算机视觉实验:图像增强应用实践
本次实验主要从基于统计、函数映射的图像增强方法和基于滤波的图像增强方法两种方法中对一些图像增强的算法进行实现。主要的编程语言为python,调用了python自带的PIL图像库用于读取图像,利用numpy进行图像运算,最后使用opencv第三方库进行对…...

ES6:Generator函数详解
ES6:Generator函数详解 1、 概念2、yield表达式2.1 yield 语句与 return 语句区别2.2 Generator函数不加yield语句,这时变成了一个单纯的暂缓执行函数2.3 yield 表达式只能用在 Generator 函数里面,用在其它地方都会报错2.4 yield 表达式如果…...