Linux(16):认识系统服务(daemons)

什么是 daemon 与系统服务

【服务】一般的说明是【常驻在记体体中的程序,且可以提供一些系统或网络功能,那就是服务】。而服务一般的英文说法是【service】。

简单的说,系统为了某些功能必须要提供一些服务(不论是系统本身还是网络方面),这个服务就称为service 。但是 service 的是需要程序的运作的,达成这个 service 的程序就称呼他为 【daemon】

举例来说,达成循环型例行性工作排程服务(service)的程序为 crond 这个daemon。

服务的名称被建立之后,被挂上 Linux使用时,通常在服务的名称之后会加上一个d ,例如例行性命令的建立的 at,与 cron 这两个服务,他的程序文件名会被取为 atd 与 crond,这个d 代表的就是 daemon 的意思。

早期 System V 的 init 管理行为中 daemon 的主要分类(Optional)

Unix 的 system V版本是个很纯种的 Unix 版本~在那种年代底下,启动系统服务的管理方式被称为SysV的 init 脚本程序的处理方式。亦即系统核心第一支呼叫的程序是 init ,然后 init 去唤起所有的系统所需要的服务,不论是本地服务还是网络服务。

基本上 init 的管理机制的几个特色如下:

1.服务的启动、关闭与观察等方式:

所有的服务启动脚本通通放置于 /etc/init.d/ 底下,基本上都是使用 bash shell script 所写成的脚本程序,需要启动、关闭、重新启动、观察状态时,可以透过如下的方式来处理:

启动:/etc/init.d/daemon start;

关闭:/etc/init.d/daemon stop;

重新启动:/etc/init.d/daemon restart;

状态观察:/etc/init.d/daemon status;

2.服务启动的分类:

init 服务的分类中,依据服务是独立启动或被一只总管程序管理而分为两大类:

独立启动模式(stand alone):服务独立启动,该服务直接常驻于内存中,提供本机或用户的服务行为,反应速度快;

总管程序(super daemon):由特殊的 xinetd 或 inetd 这两个总管程序提供 socke t对应或 port 对应的管理。当没有用户要求某 socket 或 por t时,所需要的服务是不会被启动的。若有用户要求时,xinetd 总管才会去唤醒相对应的服务程序。当该要求结束时,这个服务也会被结束掉,因为透过 xinetd 所总管,因此这个家伙就被称为 super daemon。好处是可以透过 super daemon 来进行服务的时程、联机需求等的控制,缺点是唤醒服务需要一点时间的延迟。

3.服务的相依性问题:

服务是可能会有相依性的。例如,要启动网络服务,但是系统没有网络,那就无法唤醒网络服务。如果需要联机到外部取得认证服务器的联机,但该联机需要另一个A服务的需求,但A服务没有启动,因此,认证服务就不可能会成功启动的。这就是所谓的服务相依性问题。init 在管理员自己手动处理这些服务时,是没有办法协助相依服务的唤醒的。

4.执行等级的分类:

上面说到 init 是开机后核心主动呼叫的,然后 init 可以根据用户自定义的执行等级(runlevel)来唤醒不同的服务,以进入不同的操作界面。基本上 Linux提供7个执行等级,分别是0,1,2...6 ,比较重要的是1)单人维护模式、3)纯文本模式、5)文字加图形界面。而各个执行等级的启动脚本是透过 /etc/rc.d/rc[0-6]/SXXdaemon 连结到 /etc/init.ddaemon,连结档名(SXXdaemon)的功能为:S为启动该服务,XX是数字,为启动的顺序。由于有 SXX 的设定,因此在开机时可以【依序执行】所有需要的服务,同时也能解决相依服务的问题。这点与管理员自己手动处理不太一样就是了。

5.制定执行等级默认要启动的服务:

若要建立如上提到的 SXXdaemon 的话,不需要管理员手动建立连结档,透过如下的指令可以来处理默认启动、预设不启动、观察预设启动否的行为:

预设要启动:chkconfig daemon on;

预设不启动:chkconfig dacmon off;

观察预设为启动否:chkconfig --list daemon

6.执行等级的切换行为:

当要从纯文本界面(runlevel 3)切换到图形界面(runlevel 5),不需要手动启动、关闭该执行等级的相关服务,只要【init 5】即可切换,init 会主动去分析 /etc/rc.d/re[35].d/ 这两个目录内的脚本,然后启动转换runlevel中需要的服务,就完成整体的 runlevel 切换。

systemd 使用的 unit 分类

从CentOS 7.x以后,Red Hat 系列的 distribution 放弃沿用多年的 System V 开机启动服务的流程,就是init启动脚本的方法,改用 systemd 这个启动服务管理机制。

systemd 的好处:

1.平行处理所有服务,加速开机流程:

旧的 init 启动脚本是【一项一项任务依序启动】的模式,因此不相依的服务也是得要一个一个的等待。但目前的硬件主机系统与操作系统几乎都支持多核心架构了,未相依的服务也可以同时启动。systemd 可以让所有的服务同时启动。

2.一经要求就响应的 on-demand 启动方式:

systemd 全部就是仅有一只 systemd 服务搭配 systemctl 指令来处理,无须其他额外的指令来支持。不像 systemV 还要 init, chkconfig, servic... 等等指令。此外,systemd 由于常驻内存,因此任何要求 (on-demand) 都可以立即处理后续的 daemo n启动的任务。

3.服务相依性的自我检查:

由于 systemd 可以自定义服务相依性的检查,因此如果 B 服务是架构在 A 服务上面启动的,那在没有启动 A 服务的情况下仅手动启动 B 服务时,systemd 会自动启动A服务。这样就可以免去管理员得要一项一项服务去分析的麻烦。

4.依daemon功能分类:

systemd 旗下管理的服务非常多。首先 systemd 先定义所有的服务为一个服务单位(unit),并将该 unit 归类到不同的服务类型(type)去。旧的 init 仅分为 standalone 与 super daemon 不太够用,systemd 将服务单位(unit)区分为 service, socket, target, path, snapshot,timer 等多种不同的类型(type),方便管理员的分类与记忆。

5.将多个daemons集合成为一个群组:

如同 systemV 的 init 里头有个 runlevel 的特色,systemd 亦将许多的功能集合成为一个所谓的 target 项目,这个项目主要在设计操作环境的建置,所以是集合了许多的 daemons,亦即是执行某个 target 就是执行好多个daemon的意思。

6.向下兼容旧有的 init 服务脚本:

基本上,systemd 是可以兼容于init 的启动脚本的,因此,旧的 init 启动脚本也能够透过 systemd 来管理,只是更进阶的systemd功能就没有办法支持就是了。

虽然如此,不过systemd也是有些地方无法完全取代init 的。包括:

1.在 runlevel 的对应上,大概仅有 runlevel 1,3,5 有对应到 systemd 的某些 target 类型而已,没有全部对应;

2.全部的 systemd 都用 systemctl 这个管理程序管理,而 systemctl 支持的语法有限制,不像 /etc/init.d/daemon 就是纯脚本可以自定义参数,systemctl不可自定义参数;

3.如果某个服务启动是管理员自己手动执行启动,而不是使用 systemctl 去启动的,那么systemd 将无法侦测到该服务,而无法进一步管理。

4.systemd 启动过程中,无法与管理员透过 standard input 传入讯息。因此,自行撰写 systemd 的启动设定时,务必要取消互动机制~(连透过启动时传进的标准输入讯息也要避免)

systemd 的配置文件放置目录

基本上,systemd 将过去所谓的 daemon 执行脚本通通称为一个服务单位(unit),而每种服务单位依据功能来区分时,就分类为不同的类型(type)。

基本的类型有包括系统服务、数据监听与交换的插槽档服务(socket)、储存系统状态的快照类型、提供不同类似执行等级分类的操作环境(target)等等。

配置文件都放置在底下的目录中:

/usr/lib/systemd/system/:每个服务最主要的启动脚本设定,有点类似以前的 /etc/init.d 底下的文件;

/run/systemd/system/:系统执行过程中所产生的服务脚本,这些脚本的优先序要比/usr/lib/systemd/system/ 高;

/etc/systemd/system/:管理员依据主机系统的需求所建立的执行脚本,其实这个目录有点像以前

/etc/rc.d/rc5.d/Sxx 之类的功能。执行优先序又比 /run/systemd/system/高。

也就是说,到底系统开机会不会执行某些服务其实是看 /etc/systemd/system/ 底下的设定,所以该目录底下一大堆连结档。

而实际执行的 systemd 启动脚本配置文件,其实都是放置在 /usr/lib/systemd/system/ 底下的。因此如果想要修改某个服务启动的设定,应该要去 /usr/lib/systemd/system/ 底下修改。

/etc/systemd/system/ 仅是连结到正确的执行脚本配置文件而已。所以想要看执行脚本设定,应该就得要到/usr/lib/systemd/system/底下去查阅。

systemd 的 unit 类型分类说明

可以知道 vsftpd 与 crond 其实算是系统服务(service),而 multi-user 要算是执行环境相关的类型(target type)。

根据这些扩展名的类型,几种比较常见的 systemd 的服务类型如下:

透过 systemctl 管理服务

基本上,systemd 这个启动服务的机制,主要是透过一只名为 systemctl 的指令来处理的。跟以前systemV 需要 service/chkconfig/setup/init 等指令来协助不同,systemd 就是仅有 systemctl 这个指令来处理。所以全部的行为都得要使用 systemctl 。

透过 systemctl 管理单一服务(service unit)的启动/开机启动与观察状态

一般来说,服务的启动有两个阶段,一个是【开机的时候设定要不要启动这个服务】,以及【现在要不要启动这个服务】。

bash 复制代码
systemctl [command] [unit]



Active 的 daemon现在状态?除了running 跟dead 之外,基本上有几个常见的状态:

active (running):正有一只或多只程序正在系统中执行的意思,举例来说,正在执行中的 vsftpd 就是这种模式;

active (exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行。举例来说,开机或者是挂载时才会进行一次的 quotaon 功能,就是这种模式。quotaon 不须一直执行~只须执行一次之后,就交给文件系统去自行处理,通常用 bash shell 写的小型服务,大多是属于这种类型(无须常驻内存);

active(waiting):正在执行当中,不过还再等待其他的事件才能继续处理。举例来说,打印的队列相关服务就是这种状态。虽然正在启动中,不过,也需要真的有队列进来(打印作业)这样他才会继续唤醒打印机服务来进行下一步打印的功能;

inactive::这个服务目前没有运作的意思;

daemon 的预设状态能除了enable/disable之外,还有其他的情况:

enabled:这个 daemon 将在开机时被执行;

disabled:这个 daemon 在开机时不会被执行;

static:这个 daemon 不可以自己启动(enable不可),不过可能会被其他的 enabled 的服务来唤醒(相依属性的服务)

mask:这个 daemon 无论如何都无法被启动。因为已经被强制注销(非删除)。可透过 systemctl unmask 方式改回原本状态。

透过 systemctl 观察系统上所有的服务

透过 list-units 及 list-unit-files 来观察系统上面有多少的服务存在。

bash 复制代码
systemctl [command] [--type=TYPE] [--all]


使用 systemctl list-unit-files 会将系统上所有的服务通通列出来,STATE 状态就是开机是否会加载的那个状态项目。

列出某种类别的daemon,例如 service:

透过 systemctl 管理不同的操作环境(target unit)

列出跟操作界面比较有关的 target项目:
在 CentOS 7.1的预设情况下,有 26 个target unit,而跟操作界面相关性比较高的target主要有底下几个:

graphical.target:文字加上图形界面,这个项目已经包含了底下的 multi-user.target 项目;

multi-user.target:纯文本模式;

rescue.target:在无法使用 root 登入的情况下,systemd 在开机时会多加一个额外的暂时系统,与原本的系统无关。这时可以取得 root 的权限来维护你的系统。但是这是额外系统,因此可能需要动到 chroot 的方式来取得原有的系统;

emergency.target:紧急处理系统的错误,还是需要使用 root 登入的情况,在无法使用 rescue.target 时,可以尝试使用这种模式;

shutdown.target:就是关机的流程;

getty.target:可以设定需要几个 tty 之类的,如果想要降低 tty 的项目,可以修改这个东西的配置文件;

如何知道目前的模式:

bash 复制代码
systemctl [command] [unit.target]

改变 graphical.target 以及 multi-user.targe t是透过 isolate 来处理的。

重启图形界面:

systemd 也提供了简单的指令切换模式:

suspend:暂停模式会将系统的状态数据保存到内存中,然后关闭掉大部分的系统硬件,当然,并没有实际关机,当用户按下唤醒机器的按钮,系统数据会重内存中回复,然后重新驱动被大部分关闭的硬件,就开始正常运作。唤醒的速度较快。

hibernate:休眠模式则是将系统状态保存到硬盘当中,保存完毕后,将计算机关机。当用户尝试唤醒系统时,系统会开始正常运作,然后将保存在硬盘中的系统状态恢复回来。因为数据是由硬盘读出,因此唤醒的效能与硬盘速度有关。

透过 systemctl 分析各服务之间的相依性

追踪某一个 unit 的相依性:

bash 复制代码
systemctl list-dependencies [unit] [--reverse]
# --reverse:反向追踪谁使用这个unit

可以看得出来,graphical.target 就是在 multi-user.target 底下再加上 accounts-daemon, gdm,network, rtkit-deamon, systemd-update-utmp-runlevel等服务而已。

与 systemd 的 daemon 运作过程相关的目录简介

比较重要的 systemd 启动脚本配置文件在 /usr/lib/systemd/system/,/etc/systemd/system/ 目录下。

跟系统的 daemon运作有关的目录:

/usr/lib/systemd/system/:

使用 CentOS 官方提供的软件安装后,默认的启动脚本配置文件都放在这里,这里的数据尽量不要修改~要修改时,到/etc/systemd/system底下修改较佳;

/run/systemd/system/:

系统执行过程中所产生的服务脚本,这些脚本的优先序要比 /usr/lib/systemd/system/高;

/etc/systemd/system/ :

管理员依据主机系统的需求所建立的执行脚本,这个目录有点像以前l /etc/rc.d/rc5.d/Sxx 之类的功能。执行优先序又比 /run/systemd/system/ 高;

/etc/sysconfig/*:

几乎所有的服务都会将初始化的一些选项设定写入到这个目录下,举例来说,mandb 所要更新的 man page 索引中,需要加入的参数就写入到此目录下的 man-db当中。而网络的设定则写在 /etc/sysconfig/network-scripts/ 这个目录内;

/var/lib/:

一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中。举例来说,数据库管理系统 Mariadb 的数据库默认就是写入 /var/lib/mysql/ 这个目录下;

/run/:

放置了好多 daemon 的暂存档,包括 lock file以及 PID file等等。

systemd 里头有很多的本机会用到的 socket 服务,里头可能会产生很多的 socket file。透过 systemctl 可以管理这些socket file:

bash 复制代码
systemctl list-sockets


网络服务与端口口对应简介
系统所有的功能都是某些程序所提供的,而程序则是透过触发程序而产生的。同样的,系统提供的网络服务当然也是这样的,只是由于网络牵涉到 TCP/IP的概念,所以显的更复杂一些。

http://ftp.ksu.edu.tw/

ftp://ftp.ksu.edu.tw/

两个网址都是指向 ftp.ksu.edu.tw 这个昆山科大的 FTP 网站,但是浏览器上面显示的结果却是不一样。因为指向不同的服务:一个是 http 这个 WWW 的服务,一个则是 ftp 这个文件传输服务,当然显示的结果就不同了。

port 与 daemon 的对应:

为了统一整个因特网的端口号对应服务的功能,好让所有的主机都能够使用相同的机制来提供服务与要求服务,所以就有了【通讯协议】这玩意儿。也就是说,有些约定俗成的服务都放置在同一个埠号上面。举例来说,网址列上面的 http 会让浏览器向 WWW 服务器的80埠号进行联机的要求,而 WWW 服务器也会将 httpd 这个软件激活在 port 80,这样两者才能够达成联机的。

/etc/services 可以设定让系统上面的服务与埠号对应在一起。

第一栏为 daemon 的名称、第二栏为该daemon所使用的端口号与网络数据封包协议,封包协议主要为可靠联机的TCP封包以及较快速但为非面向连接的UDP封包。

关闭网络服务

观察网络端口

关闭:

bash 复制代码
systemctl stop avahi-daemon.service
systemctl stop avahi-daemon.socket
systemctl disable avahi-daemon.service avahi-daemon.socket

systemctl 针对 service 类型的配置文件

以前,如果想要建立系统服务,就得要到 /etc/init.d/ 底下去建立相对应的 bash shell script 来处理。现在在 systemd 的环境底下,想要设定相关的服务启动环境更加方便。

systemctl 配置文件相关目录简介

服务的管理是透过systemd,而 systemd 的配置文件大部分放置于 /usr/lib/systemd/system/目录内。

但是 Red Hat 官方文件指出,该目录的文件主要是原本软件所提供的设定,建议不要修改。而要修改的位置应该放置于/etc/systemdsystem/ 目录内。

/usr/lib/systemd/system/vsftpd.service:官方释出的预设配置文件;

/etc/systemd/system/vsftpd.service.d/custom.conf:在 /etc/systemd/system 底下建立与配置文件相同文件名的目录,但是要加上 .d 的扩展名。然后在该目录下建立配置文件即可。另外,配置文件最好附档名取名为.conf较佳。在这个目录下的文件会【累加其他设定】进入 /usr/lib/systemd/system/vsftpd.service 内。

/etc/systemd/system/vsftpd.service.wants/*:此目录内的文件为链接档,设定相依服务的连结。意思是启动了 vsftpd.service之后,最好再加上这目录底下建议的服务。

/etc/systemd/system/vsftpd.service.requires/*:此目录内的文件为链接档,设定相依服务的连结。意思是在启动 vsftpd.service 之前,需要事先启动哪些服务的意思。

基本上,在配置文件里面都可以自由设定相依服务的检查,并且设定加入到哪些 target 里头去。但是如果是已经存在的配置文件,或者是官方提供的配置文件,Red Hat 是建议不要修改原设定,而是到上面提到的几个目录去进行额外的客制化设定比较好。

systemctl 配置文件的设定项目简介

分析上面的配置文件,我们大概能够将整个设定分为三个部份,就是:

[Unit]:unit 本身的说明,以及与其他相依 daemon的设定,包括在什么服务之后才启动此 unit 之类的设

定值;

[Service], [Socket], [Timer], [Mount], [PathJ...:不同的 unit type 就得要使用相对应的设定项目。我们拿的是sshd.service来当模板,所以这边就使用[Service]来设定。这个项目内主要在规范服务启动的脚本、环境配置文件档名、重新启动的方式等等。

[Install]:这个项目就是将此 unit安装到哪个target里面去的意思。

配置文件内设定规则:

1.设定项目通常是可以重复的,例如可以重复设定两个 After 在配置文件中,不过,后面的设定会取代前面的。因此,如果想要将设定值归零,可以使用类似【Afler=】的设定,亦即该项目的等号后面什么都没有,就将该设定归零了(reset)。

2.如果设定参数需要有【是/否】的项目(布尔值, boolean),可以使用1, yes, true, on 代表启动,用0, no, false,off代表关闭;

3.空白行、开头为 #; 的那一行,都代表批注;

每个部份里面还有很多的设定细项:

【Service】中可以使用的项目:

【install】内的项目:

多重的重复设定方式:以 getty 为例

CentOS 7 开机完成后,有6个终端机可以使用: tty1~tty6 。是由agetty这个指令达成的。

终端机的功能,主要管理的是 getty.target这个target unit,不过,实际产生tty1~tty6 的则是由 getty@.service 所提供的.

比较重要的是ExecStart 项目。去 man agetty时,发现到它的语法应该是【agetty--noclear tty1】之类的字样,因此,如果要启动六个tty 的时候,基本上应该要有六个启动配置文件。亦即是可能会用到 getty1.service, getty2.servic...getty6.service 才对。 这样控管很麻烦,所以,才会出现这个@的项目。

会发现会多出六个怪异的 service。拿 getty@tty1.service 来说明一下:当我们执行完 getty.target 之后,他会持续要求 getty@tty1.service 等六个服务继续启动。那 systemd 就会这么作:

1.先看 /usr/lib/systemd/system,/etc/systemd/system/ 有没有 getty@tty1.service 的设定,若有就执行,若没有则执行下一步;

2.找 getty@.service 的设定,若有则将 @ 后面的数据带入成 %I 的变量,进入 getty@.service 执行。

这也就是说,其实 getty@tty1.service 实际上是不存在的,他主要是透过 getty@.service来执行~也就是说,getty@.service 的目的是为了要简化多个执行的启动设定 ,他的命名方式是这样的:

因此当有范例名称带入时,则会有一个新的服务名称产生出来。

再回头看看 getty@.service 的启动脚本:

bash 复制代码
ExecStart=-/sbin/agetty --noclear %l $TERM

那个%I指的就是【范例名称】,根据 getty.target 的信息输出来看,getty@tty1.service 的 %I 就是 tty1。因此执行脚本就会变成【/sbin/agetty --noclear tty1】。所以可以以一个配置文件来启动多个tty1给用户登入。

将 tty 的数量由 6 个降低到 4 个

是在 systemd 的登入配置文件 /etc/systemd/logind.conf 里面规范的。

cat /etc/systemd/logind.conf

修改 NAutoVTs = 4,ReserveVT=0,取消批注,然后关闭不小心启动的 tty5,tty6,并重新启动 getty.target .

可以使用 下面的指令重新启动:

bash 复制代码
systemctl start getty@tty5.service

systemctl 针对 timer 的配置文件

除了 crond 之外,使用 systemd 内建的 time 来处理各种任务。

systemd.timer 的优势

由于所有的 systemd 的服务产生的信息都会被纪录(log),因此比 crond 在 debug 上面要更清楚方便的多;

各项 timer 的工作可以跟 systemd 的服务相结合;

各项 timer 的工作可以跟 control group (cgroup,用来取代 /etc/secure/limit.conf 的功能)结合,来限制该工作的资源利用;

有弱。。。点:例如 systemd 的 timer 并没有 email 通知的功能(除非自己写一个),也没有类似 anacron的一段时间内的随机取样功能(random_delay)。

此外,相对于 crond 最小的单位到分,systemd是可以到秒甚至是毫秒的单位哩。

任务需求

基本上,想要使用 systemd 的 timer 功能,必须要有几个要求:

系统的 timer.target 一定要启动;

要有个 sname.service 的服务存在 (sname 是自己指定的名称);

要有个 sname.timer 的时间启动服务存在;

sname.timer 的设定值

可以到 /etc/systemd/system 底下去建立这个*.timer档,设定主要有底下这些:(man systemd.timer & man systemd.time)

使用于 OnCalendar 的时间

从crontab转成这个timer 功能,那么对于时间设定的格式就得要了解。基本上的格式如下所示:

也可以直接使用间隔时间来处理。常用的间隔时间单位有:

us或usec:微秒( 1 0 − 6 10^{-6} 10−6秒);

ms或msec:毫秒( 1 0 − 3 10^{-3} 10−3秒)

s, sec, second, seconds;

m, min, minute, minutes;

h, hr,hour, hours;

d, day, days;

w, week, weeks;

month, monthsy;

year, years;

常见的使用范例有:
也可以使用英文常用的口语化日期代表:

CentOS 7.x 预设启动的服务简要说明

主要是针对 Linux单机服务器的角色来说明的:
上面的服务是 CentOS 7.x 预设有启动的,这些预设启动的服务很多是针对桌面计算机所设计的,所以啰,如果 Linux 主机用途是在服务器上面的话,那么有很多服务是可以关闭的。

如果还有某些不明白的服务想要关闭的,请务必要搞清楚该服务的功能为何。

举例来说,那个 rsyslog 就不能关闭,如果你关掉他的话,系统就不会记录登录文件,那系统所产生的警告讯息就无法记录起来,将无法进行debug。

预设并没有启动的其他服务:

《鸟哥的Linux私房菜-基础篇》学习笔记

相关推荐
痞老板A小安装C47 分钟前
Redis 过期策略和内存淘汰策略
数据库·redis·缓存
陈燚_重生之又为程序员2 小时前
梧桐数据库的高效索引技术分析
数据库
hellolio2 小时前
PostgreSQL详细安装教程
数据库·postgresql
鳄鱼的眼泪13 小时前
mysql深度分页优化
数据库·mysql
yava_free3 小时前
介绍一下mysql binlog查看指定数据库的方法
java·数据库·mysql
漫天转悠3 小时前
MySQL中in和exists的区别
数据库·mysql
Octopus20773 小时前
【Linux】vim的使用
linux·笔记·学习·vim
一个假的前端男3 小时前
VMware安装CentOS 9 及mysql的安装
linux·运维·centos
Cosmoshhhyyy3 小时前
mysql低版本中update_time不自动更新问题
数据库·mysql
北京迅为3 小时前
【北京迅为】iTOP-4412全能版使用手册-第七章 Android 4.4系统编译
linux·嵌入式硬件·4412开发板