systemd源码分析,system函数源码

http://www.itjxue.com  2023-01-21 11:45  来源:未知  点击次数: 

如何编写 Systemd 服务文件

一种以 .service 结尾的单元(unit)配置文件,用于控制由 systemd 控制或监视的进程。简单说,用于后台以守护精灵(daemon)的形式运行程序。

编写 Systemd service

基本结构

Systemd 服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义、以及安装部分。

和 SysV init 脚本的差异

过去,*nix 服务(守护精灵)都是用 SysV 启动脚本启动的。SysV 启动脚本就是 Bash 脚本,通常在 /etc/init.d 目录下,可以被一些标准参数如 start,stop,restart 等调用。启动该脚本通常意味着启动一个后台守护精灵(daemon)。shell 脚本常见的缺点就是,慢、可读性不强、太详细又很傲娇。虽然它们很灵活(毕竟那就是代码呀),但是有些事只用脚本做还是显得太困难了,比如安排并列执行、正确监视进程,或者配置详细执行环境。

SysV 启动脚本还有一个硬伤就是,臃肿,重复代码太多。因为上述的“标准参数”必须要靠各个脚本来实现,而且各个脚本之间的实现都差不多(根本就是从一个 skeleton 骨架来的)。而 Systemd 则进行了统一实现,也就是说在 Systemd service 中完全就不需要、也看不到这部分内容。这使得 Systemd 服务非常简明易读,例如 NetworkManager 这一重量级程序的服务,算上注释一共才有 19 行。而它相应的 SysV 启动脚本头 100 行连标准参数都没实现完。

Systemd 兼容 Sysv 启动脚本,这也是为什么这么久我们仍然需要一个 systemd-sysvinit 软件包的原因。但是根据以上理由,最好针对所有您安装的守护精灵都使用原生 Systemd 服务来启动。另外,Systemd 服务可无缝用于所有使用 Systemd 的发行版,意思是 Arch 下编写的脚本拿过来依然能够使用。

通常来说,上游应该在发布源代码的同时发布 Systemd 服务,但如果没发布,你可以对照本教学来为它们写一个并贡献给它们。

Systemd 语法

Systemd 语法和 .desktop 文件的语法比较像,也比较类似 Windows 下的 .ini 文件,因此无论对于打包者还是最终用户都是非常容易上手的。

主要格式请见下面的小例子,这里需要说明三点:

Systemd 单元文件中的以 “#” 开头的行后面的内容会被认为是注释

Systemd 下的布尔值,1、yes、on、true 都是开启,0、no、off、false 都是关闭。注:

仅限于 Systemd 文件,比如:

RemainOnExit=yes

并不适用于该文件中嵌入的 shell 语句,比如:

ExecStartPre=/usr/bin/test "x${NETWORKMANAGER}" = xyes

这里的 yes 就不能替换。因为等号后面是一条嵌入的 shell 语句。

Systemd 下的时间单位默认是秒,所以要用毫秒(ms)分钟(m)等请显式说明。

一个小例子

NetworkManager 的 Systemd service:

[Unit]

Description=Network Manager

After=syslog.target

Wants=remote-fs.target network.target

[Service]

Type=dbus

BusName=org.freedesktop.NetworkManager

ExecStart=/usr/sbin/NetworkManager --no-daemon

EnvironmentFile=/etc/sysconfig/network/config

ExecStartPre=/usr/bin/test "x${NETWORKMANAGER}" = xyes

# Suppress stderr to eliminate duplicated messages in syslog. NM calls openlog()

# with LOG_PERROR when run in foreground. But systemd redirects stderr to

# syslog by default, which results in logging each message twice.

StandardError=null

[Install]

WantedBy=multi-user.target

Also=NetworkManager-wait-online.service

以下我们以编写 He.net IPv6 单元文件为例。

定义控制单元 [Unit]

在 Systemd 中,所有引导过程中 Systemd 要控制的东西都是一个单元。Systemd 单元类型有:

系统服务

套接字(socket)

设备

挂载点

自动挂载点

SWAP 文件

分区

启动对象(startup target)

文件系统路径

定时器

简单说,Systemd 把 *nix 里那些分散开发因此宏观看变成一团杂碎的东西重新统一命名了。单元名就是你写的这个 .service 文件的名称。但不只有 .service 后缀的文件才可以是一个单元,单元还可以有 .target, .path 等后缀,具体可以去 /usr/lib/systemd/system 下了解。但那种后缀要么由 Systemd 上游开发者写好随 systemd 软件包分发,要么由我们的 Base:system 团队添加,一般用户是不太需要写其它后缀的控制单元的。

我们先要声明我们在定义控制单元:

[Unit]

单元名称就不用写了,我们要写一条单元描述:

[Unit]

Description=Daemon to start He.net IPv6

下面我们要讲解一下 Systemd 是如何控制各个单元之间的关系的。它和 RPM 的 specfile 的依赖关系控制的语法非常相似(毕竟都是红帽一家的):

Requires: 这个单元启动了,那么它“需要”的单元也会被启动; 它“需要”的单元被停止了,它自己也活不了。但是请注意,这个设定并不能控制某单元与它“需要”的单元的启动顺序(启动顺序是另外控制的),即 Systemd 不是先启动 Requires 再启动本单元,而是在本单元被激活时,并行启动两者。于是会产生争分夺秒的问题,如果 Requires 先启动成功,那么皆大欢喜; 如果 Requires 启动得慢,那本单元就会失败(Systemd 没有自动重试)。所以为了系统的健壮性,不建议使用这个标记,而建议使用 Wants 标记。可以使用多个 Requires。

RequiresOverridable:跟 Requires 很像。但是如果这条服务是由用户手动启动的,那么 RequiresOverridable 后面的服务即使启动不成功也不报错。跟 Requires 比增加了一定容错性,但是你要确定你的服务是有等待功能的。另外,如果不由用户手动启动而是随系统开机启动,那么依然会有 Requires 面临的问题。

Requisite:强势版本的 Requires。要是这里需要的服务启动不成功,那本单元文件不管能不能检测等不能等待都立刻就会失败。

Wants:推荐使用。本单元启动了,它“想要”的单元也会被启动。但是启动不成功,对本单元没有影响。

Conflicts:一个单元的启动会停止与它“冲突”的单元,反之亦然。注意这里和后面的启动顺序是“正交”的:

两个相互冲突的单元被同时启动,要么两个都启动不了(两者都是第三个单元的 Requires),要么启动一个(有一个是第三个单元的 Requires,另一个不是),不是 Requires 的那个会被停止。要是两者都不是任何一个单元的 Requires,那么 Conflicts 别的那个单元优先启动,被 Conflicts 的后启动,要是互相写了,那么两个都启动不了。

OnFailure:很明显,如果本单元失败了,那么启动什么单元作为折衷。

好了,现在我们来想象一下,我们的单元(Ipv6 隧道)应该想要什么呢?很显然是一个连通着的网络。有一个 Systemd 默认提供的对象叫做 network-online.target(默认的 target 列表可见 systemd.special,必看,因为你大多数时候 Wants 的都是一个固定的系统状态而不是其它 systemd 服务),正正好好能够提供我们需要的环境。于是:

[Unit]

Description=Daemon to start He.net IPv6

Wants=network-online.target

下面我们需要定义一下服务启动顺序,不然连 / 目录所在的硬盘都没挂载就开始干活,上哪儿找程序去呀。Systemd 服务启动顺序主要使用以下两个标记定义的:

Before/After:要是一个服务 Before 另一个服务,那么在并行启动时(Systemd 总是用进程 0 并行启动所有东西,然后通过这两个标记来二次等待排序),那另一个服务这时就会等这个服务先启动并返回状态,注意是先启动而不是启动成功,因为失败也是一种状态,一定要成功才启动另一个服务是通过依赖关系定义的。反之 After 亦然。

下面说下“关机”(可以是挂起,这时候有些服务是依然在跑的,比如网络唤醒)时候的顺序:如果两个服务都是要关掉的,Before 是先关自己,After 是先关别人,这很好理解; 但如果一个服务是要关,而另一个是要开的,那么不管 Before/After 写了什么,总是优先关闭而不是开始。也就是比如服务 A Before 服务 B,但是服务 B 是在关,而服务 A 是在 restart,那么服务 B 的顺序在服务 A 的前面。

好啦,我们的单元应该在什么的前后启动呢?它不需要一定在什么服务前面跑起来,这不像 ifup 和 dhcp,网络起不来获取 ip 肯定没用。我们只需要有网就可以了。“有网”在 Systemd 中也是由一个默认 target:network.target 提供的,于是我们的控制单元就定义好了:

[Unit]

Description=Daemon to start He.net IPv6

Wants=network-online.target

After=network.target

定义服务本体 [service]

在定义完了 Systemd 用来识别服务的单元后,我们来定义服务本体,依然是声明:

[Service]

然后是声明服务类型:

[Service]

Type=

Systemd 支持的服务类型有以下几类:

simple 默认,这是最简单的服务类型。意思就是说启动的程序就是主体程序,这个程序要是退出那么一切皆休。这在图形界面里非常好理解,我打开 Amarok,退出它就没有了。但是命令行的大部分程序都不会那么设计,因为命令行的一个最基本原则就是一个好的程序不能独占命令行窗口。所以输入命令,回车,接着马上返回给你提示符,但程序已经执行了。所以只有少数程序比如 python xxx.py 还使用这种方式。在这种类型下面,如果你的主程序是要响应其它程序的,那么你的通信频道应该在启动本服务前就设好(套接字等),因此这种类型的服务,Systemd 运行它后会立刻就运行下面的服务(需要它的服务),这时没有套接字后面的服务会失败,写 After 也没用,因为 simple 类型不存在主进程退出的情况也就不存在有返回状态的情况,所以它一旦启动就认为是成功的,除非没起来。

forking 标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。你要是使用的这种方式,最好也指定下 PIDFILE=,不要让 Systemd 去猜,非要猜也可以,把 GuessMainPID 设为 yes。

判断是 forking 还是 simple 类型非常简单,命令行里运行下你的程序,持续占用命令行要按 Ctrl + C 才可以的,就不会是 forking 类型。

创建 PIDFILE 是你为它写服务的程序的任务而不是 Systemd 的功能,甚至也不是 Sysvinit 脚本的功能。参考 startproc创建pid file的问题了解进一步的知识。因此如果你的程序确实是 forking 类型,但就是没实现创建 PIDFILE 的功能,那么建议使用 ExecStartPost= 结合 shell 命令来手动抓取进程编号并写到 /var/run/xxx.pid。

oneshot 顾名思义,打一枪换一个地方。所以这种服务类型就是启动,完成,没进程了。常见比如你设置网络,ifup eth0 up,就是一次性的,不存在 ifup 的子进程(forking 那样),也不存在主进程(simple 那样),它运行完成后便了无痕迹。因为这类服务运行完就没进程了,我们经常会需要 RemainAfterExit=yes。后面配置的意思是说,即使没进程了,我们也要 Systemd 认为该服务是存在并成功了的。所以如果你有一个这样的服务,服务启动后,你再去 ifup eth0 up,这时你再看服务,依然显示是 running 的。因为只要在执行那条一次性命令的时候没出错,那么它就永远认为它是成功并一直存在的,直到你关闭服务。

dbus 这个程序启动时需要获取一块 DBus 空间,所以需要和 BusName= 一起用。只有它成功获得了 DBus 空间,依赖它的程序才会被启动。

一般人也就能用到上面四个,还有两种少见的类型:

notify 这个程序在启动完成后会通过 sd_notify 发送一个通知消息。所以还需要配合 NotifyAccess 来让 Systemd 接收消息,后者有三个级别:none,所有消息都忽略掉; main,只接受我们程序的主进程发过去的消息; all,我们程序的所有进程发过去的消息都算。NotifyAccess 要是不写的话默认是 main。

idle 这个程序要等它里面调度的全部其它东西都跑完才会跑它自己。比如你 ExecStart 的是个 shell 脚本,里面可能跑了一些别的东西,如果不这样的话,那很可能别的东西的控制台输出里会多一个“启动成功”这样的 Systemd 消息。

由于 He.net 的 IPv6 是用 iproute2 的 ip 命令来弄的,所以是一个 oneshot 一次性服务。

[Service]

Type=oneshot

RemainAfterExit=yes

接下来要设置 ExecStart, ExecStop。如果程序支持的话,你还可以去设置 ExecReload,Restart 等。注意,这里设置的是它们 Reload/Restart 的方式,但并不代表没有它们 Systemd 就不能完成比如 systemctl restart xxx.service 这样的任务,程序有支持自然最好,程序不支持那就先 stop 再 start 咯。同样有特殊要求的时候你也可以去设置比如 ExecStartPre/ExecStartPost,RestartSec,TimeoutSec 等其它东西,参考链接里都有使用方法。

这里要特殊讲一下 ExecStart:

如果你服务的类型不是 oneshot,那么它只可以接受一个命令,参数不限,比如你先 ip tunnel create 再 ip tunnel0 up,那是两个 ip 命令,如果你不是 oneshot 类型这样是不行的。

如果有多条命令(oneshot 类型),命令之间以分号 ; 分隔,跨行可用反斜杠 \。

除非你的服务类型是 forking,否则你在这里输入的命令都会被认为是主进程,不管它是不是。

于是我们的 [Service] 就写好了:

[Service]

Type=oneshot

RemainAfterExit=yes

ExecStart=/usr/sbin/ip tunnel add he-ipv6 mode sit remote 66.220.18.42 local 108.170.7.158 ttl 255 ; \

/usr/sbin/ip link set he-ipv6 up ; \

/usr/sbin/ip addr add 2001:470:c:1184::2/64 dev he-ipv6 ; \

/usr/sbin/ip route add ::/0 dev he-ipv6 ; \

/usr/sbin/ip -6 addr

ExecStop=/usr/sbin/ip route delete ::/0 dev he-ipv6 ; \

/usr/sbin/ip -6 addr del 2001:470:c:1184::2/64 dev he-ipv6 ; \

/usr/sbin/ip link set he-ipv6 down ; \

/usr/sbin/ip tunnel del he-ipv6

安装服务 [install]

这可能有点绕,我服务文件都弄好了,放到 /etc/systemd/system(供系统管理员和用户使用),/usr/lib/systemd/system(供发行版打包者使用)了,不就是安装好了嘛。

这里说的是一种内部状态,默认你放对位置它显示的是 disabled,unloaded,所以我们要在 Systemd 内部对它进行一下 load,没人要的东西是不需要安装的(我们不收渣渣),所以我们要告诉 Systemd 它是有人要的,被谁要。一般都是被

[Install]

WantedBy=multi-user.target

要(multi-user.target 表示多用户系统好了,简单理解就是你可以登入了)。这样在 multi-user.target 启用时,我们的服务也就会被启用了。

[Install] 部分下除了 WantedBy 还有两种属性,分别是:

Alias= 给你自己的别名,这样 systemctl command xxx.service 的时候就可以不输入完整的单元名称。比如你给 NetworkManager 一个别名叫 Alias=nm,那你就可以 systemctl status nm.service 查看实际是 NetworkManager.service 的服务了。

Also= 安装本服务的时候还要安装别的什么服务。比如我们的 He.net 脚本按理应该需要一个 iproute2.service 作为 also,但是 iproute2 实际上不需要 systemd 控制,所以就没写。它和 [Unit] 定义里面的依赖关系相比,它管理的不是运行时依赖,而是安装时。安装好了之后启动谁先谁后,谁依赖谁,和 Also= 都没有关系。

如何在Debian上使用systemd管理系统

转载现在就让我们来看看 systemd 是怎么改变你管理系统的习惯的。在使用 systemd 之前,你得先把 sysvinit 保存起来,以便在 systemd 出错的时候还能用 sysvinit 启动系统。这种方法只有在没安装 systemd-sysv 的情况下才能生效,具体操作方法如下:

1.# cp -av /sbin/init /sbin/init.sysvinit 在紧急情况下,可以把下面的文本:

1.init=/sbin/init.sysvinit添加到内核启动参数项那里。

systemctl 的基本用法systemctl 的功能是替代“/etc/init.d/foo start/stop”这类命令,另外,其实它还能做其他的事情,这点你可以参考 man 文档。

一些基本用法:

?systemctl - 列出所有单元(UNIT)以及它们的状态(这里的 UNIT 指的就是系统上的 job 和 service)

?systemctl list-units - 列出所有 UNIT

?systemctl start [NAME...] - 启动一项或多项 UNIT

?systemctl stop [NAME...] - 停止一项或多项 UNIT

?systemctl disable [NAME...] - 将 UNIT 设置为开机不启动

?systemctl list-unit-files - 列出所有已安装的 UNIT,以及它们的状态

?systemctl --failed - 列出开机启动失败的 UNIT

?systemctl --type=mount - 列出某种类型的 UNIT,类型包含:service, mount, device, socket, target

?systemctl enable debug-shell.service - 将一个 shell 脚本设置为开机启动,用于调试

为了更方便处理这些 UNIT,你可以使用 systemd-ui 软件包,你只要输入 systemadm 命令就可以使用这个软件。

你同样可以使用 systemctl 实现转换运行级别、重启系统和关闭系统的功能:

?systemctl isolate graphical.target - 切换到运行级别5,就是有桌面的运行级别

?systemctl isolate multi-user.target - 切换到运行级别3,没有桌面的运行级别

?systemctl reboot - 重启系统

?systemctl poweroff - 关机

所有命令,包括切换到其他运行级别的命令,都可以在普通用户的权限下执行。

journalctl 的基本用法systemd 不仅提供了比 sysvinit 更快的启动速度,还让日志系统在更早的时候启动起来,可以记录内核初始化阶段、内存初始化阶段、前期启动步骤以及主要的系统执行过程的日志。所以,以前那种需要通过对显示屏拍照或者暂停系统来调试程序的日子已经一去不复返啦。

systemd 的日志文件都被放在 /var/log 目录。如果你想使用它的日志功能,需要执行一些命令,因为 Debian 没有打开日志功能。命令如下:

1.# addgroup --system systemd-journal2.# mkdir -p /var/log/journal3.# chown root:systemd-journal /var/log/journal4.# gpasswd -a $user systemd-journal 通过上面的设置,你就可以以普通用户权限使用 journal 软件查看日志。使用 journalctl 查询日志可以获得一些比 syslog 软件更方便的玩法:

?journalctl --all - 显示系统上所有日志,以及它的用户

?journalctl -f - 监视系统日志的变化(类似 tail -f /var/log/messages 的效果)

?journalctl -b - 显示系统启动以后的日志

?journalctl -k -b -1 - 显示上一次(-b -1)系统启动前产生的内核日志

?journalctl -b -p err - 显示系统启动后产生的“ERROR”日志

?journalctl --since=yesterday - 当系统不会经常重启的时候,这条命令能提供比 -b 更短的日志记录

?journalctl -u cron.service --since='2014-07-06 07:00' --until='2014-07-06 08:23' - 显示 cron 服务在某个时间段内打印出来的日志

?journalctl -p 2 --since=today - 显示优先级别为2以内的日志,包含 emerg、alert、crit三个级别。所有日志级别有: emerg (0), alert (1), crit (2), err (3), warning (4), notice (5), info (6), debug (7)

?journalctl yourlog.log - 将二进制日志文件复制成文本文件并保存到当前目录

Journal 和 syslog 可以很好的共存。而另一方面,一旦你习惯了操作 journal,你也可以卸载掉所有 syslog 的软件,比如 rsyslog 或 syslog-ng。

如果想要得到更详细的日志信息,你可以在内核启动参数上添加“systemd.log_level=debug”,然后运行下面的命令:

1.# journalctl -alb 你也可以编辑 /etc/systemd/system.conf 文件来修改日志级别。

利用 systemd 分析系统启动过程systemd 可以让你能更有效地分析和优化你的系统启动过程:

?systemd-analyze - 显示本次启动系统过程中用户态和内核态所花的时间

?systemd-analyze blame - 显示每个启动项所花费的时间明细

?systemd-analyze critical-chain - 按时间顺序打印 UNIT 树

?systemd-analyze dot | dot -Tsvg systemd.svg - 为开机启动过程生成向量图(需要安装 graphviz 软件包)

?systemd-analyze plot bootplot.svg - 产生开机启动过程的时间图表

systemd 虽然是个年轻的项目,但已有大量文档。首先要介绍给你的是Lennart Poettering 的 0pointer 系列。这个系列非常详细,非常有技术含量。另外一个是免费桌面信息文档,它包含了最详细的关于 systemd 的链接:发行版特性文件、bug 跟踪系统和说明文档。你可以使用下面的命令来查询 systemd 都提供了哪些文档:

1.# man systemd.index 不同发行版之间的 systemd 提供的命令基本一样,最大的不同之处就是打包方式。

systemd的新特性及unit常见类型分析

systemd是Linux下的中央系统及设定管理程式(init),包括有守护进程,程序库跟应用程序。开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并以此实现系统初始化时服务的并行启动,同时达到降低shell的系统开销,最终替代现在常用的system v与BSD风格init程序。

systemd组件与System V风格init相比,

Systemd特点:

? 平行处理所有服务:

systemd可以并行启动不相依的服务。

? on-deamon启动方式

systemd依靠systemctl命令就可以控制systemd,无需其他命令。常驻内存,因此任何要求 (on-demand) 都可以立即处理后续的 daemon 启动的任务

? 服务相依的自我检查:

例如:B服务是架构在A服务上,你手动启动B服务systemd会自动启动A服务。

? 功能分类

system所管理的服务非常之多,它定义了一个服务就是一个unit,相同的unit分为同一类型,systemd 将服务单位 (unit) 区分为 service, socket, target, path,snapshot, timer 等多种不同的类型(type), 方便管理员的分类与记忆。

? 将多个 daemons 集合成为一个群组

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

? 向下兼容Init服务脚本

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

Systemd的核心概念是:unit,unit由其相关配置文件进行标识,识别和配置,文件中主要包含了系统服务、监听的socket、保存的快照以及其它与init相关的信息; 这些配置文件主要保存在:

/usr/lib/systemd/system

/run/systemd/system

/etc/systemd/system

target

system所管理的服务非常之多,它定义了一个服务就是一个unit,相同的unit分为同一类型,systemd 将服务单位 (unit) 区分为 service, socket, target, path,snapshot, timer 等多种不同的类型(type), 为了方便管理员的分类、记忆与管理,把多个unit 集合在一起,组成一个target,执行这个target即可执行对应下的多个unit。

systemd将过去的运行级别划分成对应的target,如下:

运行级别:

0 == runlevel0.target, poweroff.target

1 == runlevel1.target, rescue.target

2 == runlevel2.tartet, multi-user.target

3 == runlevel3.tartet, multi-user.target

4 == runlevel4.tartet, multi-user.target

5 == runlevel5.target, graphical.target

6 == runlevel6.target, reboot.target

service unit file:

通常由三部分组成:

[Unit]:定义与Unit类型相关的通用选项;用于提供unit的描述信息、unit行为及依赖关系等;

[Service]:与特定类型相关的专用选项;此处为Service类型;

[Install]:定义由“systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项;

Unit段的常用选项:

Service段的常用选项:

Install段的常用选项:

过程:

写unit文件可以使用yum 安装http服务来参考写

源码安装http

为httpd编写unit文件

经我测试,如果type设置为:simple,启动程序直接由execstart后面的命令直接运行,并且直接运行在后台中,命令执行起来非常快,但是httpd服务没那么快起来,简单来说,type设置为simple,命令执行虽然快,但因为主进程需要启动子程序,所以直接使用浏览器浏览是看不到效果的;如果设置为forking,命令执行起来很慢,会中断一段时间,但是执行完成后,可以马上浏览看到效果, 并且使用simple有个弊端,因为httpd开辟了很多子程序提供服务,主进程的作用就是启动子进程,当启动完成以后,主进程会结束自身,所以再次使用systemctl status httpd查看,就会显示inactive状态,但其实已经启动了 。如果把type设置为:forking,则不会出现这个问题

service的type详细说明:

接下来可以使用systemctl命令来管理httpd了

至此,源码安装http和编写 unit文件并且实现systemd对其管理的实验成功~~~( ^-^ )

为什么我写的systemd脚本不工作

Systemd服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义、以及安装部分。和SysVinit脚本的差异过去,*nix服务(守护精灵)都是用SysV启动脚本启动的。SysV启动脚本就是Bash脚本,通常在/etc/init.d目录下,可以被一些标准参数如start,stop,restart等调用。启动该脚本通常意味着启动一个后台守护精灵(daemon)。shell脚本常见的缺点就是,慢、可读性不强、太详细又很傲娇。虽然它们很灵活(毕竟那就是代码呀),但是有些事只用脚本做还是显得太困难了,比如安排并列执行、正确监视进程,或者配置详细执行环境。SysV启动脚本还有一个硬伤就是,臃肿,重复代码太多。因为上述的“标准参数”必须要靠各个脚本来实现,而且各个脚本之间的实现都差不多(根本就是从一个skeleton骨架来的)。而Systemd则进行了统一实现,也就是说在Systemdservice中完全就不需要、也看不到这部分内容。这使得Systemd服务非常简明易读,例如NetworkManager这一重量级程序的服务,算上注释一共才有19行。而它相应的SysV启动脚本头100行连标准参数都没实现完。Systemd兼容Sysv启动脚本,这也是为什么这么久我们仍然需要一个systemd-sysvinit软件包的原因。但是根据以上理由,最好针对所有您安装的守护精灵都使用原生Systemd服务来启动。另外,Systemd服务可无缝用于所有使用Systemd的发行版,意思是Arch下编写的脚本拿过来依然能够使用。通常来说,上游应该在发布源代码的同时发布Systemd服务,但如果没发布,你可以对照本教学来为它们写一个并贡献给它们。关于SysVinit启动脚本的编写可见openSUSE:Packaging_init_scripts,这主要用于你的服务器,毕竟服务器追求稳定软件更新的不是很勤(但你一定不知道欧盟汽车里的车载系统必须是Systemd)。真正开始前需要注意的问题如上所述,Systemd的service文件是完全跨发行版的,所以有时候没有必要重造轮子。真正编写你的服务前,请确认它在各大发行版中完全就不存在:我们的Systemd服务集合FedoraSystemd服务集合ArchLinuxSystemd服务集合GentooSystemd服务集合Debian中的少量Systemd服务ubuntu中的少量Systemd服务Systemd语法Systemd语法和.desktop文件的语法比较像,也比较类似Windows下的.ini文件,因此无论对于打包者还是最终用户都是非常容易上手的。主要格式请见下面的小例子,这里需要说明三点:Systemd单元文件中的以“#”开头的行后面的内容会被认为是注释Systemd下的布尔值,1、yes、on、true都是开启,0、no、off、false都是关闭。注:仅限于Systemd文件,比如:RemainOnExit=yes并不适用于该文件中嵌入的shell语句,比如:ExecStartPre=/usr/bin/test"x${NETWORKMANAGER}"=xyes这里的yes就不能替换。因为等号后面是一条嵌入的shell语句。Systemd下的时间单位默认是秒,所以要用毫秒(ms)分钟(m)等请显式说明。一个小例子NetworkManager的Systemdservice:[Unit]Description=NetworkManagerAfter=syslog.targetWants=remote-fs.targetnetwork.target[Service]Type=dbusBusName=org.freedesktop.NetworkManagerExecStart=/usr/sbin/NetworkManager--no-daemonEnvironmentFile=/etc/sysconfig/network/configExecStartPre=/usr/bin/test"x${NETWORKMANAGER}"=xyes#Suppressstderrtoeliminateduplicatedmessagesinsyslog.NMcallsopenlog()#withLOG_PERRORwhenruninforeground.Butsystemdredirectsstderrto#syslogbydefault,whichresultsinloggingeachmessagetwice.StandardError=null[Install]WantedBy=multi-user.targetAlso=NetworkManager-wait-online.service

fakeapp训练结束后用保存吗

参数可以让软件自由度更高。Fakeapp的参数并不算多,但是也非常使用。本文就讲解下几个重要的参数。参数设置界面可以通过点击SETTINGS打开。

参数修改无需点击保存,一旦修改直接生效。

Processor:GPU/CPU

这个选项用来指定运行环境,是选着GPU还是CPU。 一般来说如果你有显卡肯定选GPU,如果没有就选CPU,GPU的速度比CPU快几十倍的样子。

Batch Size:批量大小

这是一个深度学习中的专有名词,在训练的模型的时候并不是一次训练所有图片,而是分批进行训练。原则上来说越大越好(2的指数),但是数字越大消耗的显存越到,需要的配置越高。

Save Period: 保存间隔

默认为100,你可以根据自己的需要修改。

Nodes: 神经节点数

一般不修改,越大能力越强,需要配置越高。 如果你的电脑配置较低,可以适当降低这个值,比如改为256

Layer: 神经网络层数

一般不修改,越大能力越强,需要配置越高。

Mem Growth:内存增长

从理解上来说是,内存是否自动增长。

Men Ratio: 使用内存量 0.1/0.2/0.3

控制使用显存的大小。默认为自动,如果调整可能会出错。

Driection: A to B 转换方向

一般默认,也可以修改成B to A ,意思就是把B变成A。

Blur Size : 模糊的大小

融合的时候边缘模糊参数,如果感觉边缘比较生硬,可以适当增大这个参数。

Kernel size :卷积核的大小

这个嘛…不懂不要动了。

更多关于 AI换脸,Deepfakes, Fakeapp的问题可以去 Deepfakes中文网。

Fakeapp 入门教程(3):参数篇的更多相关文章

【转帖】Systemd 入门教程:命令篇

Systemd 入门教程:命令篇 Copy From 感觉 ...

Systemd 入门教程:实战篇

Systemd 入门教程:实战篇 上一篇文章,介绍了 Systemd 的主要命令,这篇文章主要介绍如何使用 Systemd 来管理我们的服务,以及各项的含义: 一.开机启动 对于那些支持 System ...

Linux 命令详解(八)Systemd 入门教程:实战篇

Systemd 入门教程:实战篇

Linux 命令详解(七)Systemd 入门教程:命令篇

Systemd 入门教程:命令篇

(转)Systemd 入门教程:命令篇

Systemd 入门教程:命令篇 原文: Systemd 入门 ...

DataVeryLite入门教程(二) Entity篇

DataVeryLite 是基于.net 4.0的数据库持久化ORM框架. 目前支持的数据库有Sqlserver,Mysql,Oracle,Db2,PostgreSql,Sqlite和Access. ...

Linux Capabilities 入门教程:概念篇

原文链接:Linux Capabilities 入门教程:概念篇 Linux 是一种安全的操作系统,它把所有的系统权限都赋予了一个单一的 root 用户,只给普通用户保留有限的权限.root 用户拥有 ...

Fakeapp 入门教程(1):安装篇!

在众多AI换脸软件中Fakeapp是流传最广,操作最简单的一款,当然他同样也是源于Deepfakes. 这款软件在设计上确实是花了一些心事,只要稍加点拨,哪怕是再小白的人也能学会.下面我就做一个入门教 ...

Fakeapp 入门教程(2):使用篇!

Fakeapp软件的使用主要分成了三个步骤, 使用之前请确保你的电脑配置还可以,推荐配置是:一张显存大于4G的N卡.Fakeapp是有支持CPU选项,但是用CPU跑非常慢. 获取脸部图片 训练模型 生 ...

随机推荐

Unity [RequireComponent(typeof(组件名))]

VMWare复制虚拟机系统后,模块“Disk”无法启动【转】

1.找到虚拟机所在的目录 将 .vmx文件打开 将文件vmci0.present = "TRUE" 改为 vmci0.present = "FALSE" 2.删 ...

ArrayList相关方法介绍及源码分析

目录 ArrayList简介: ArrayList 相关方法介绍 代码表示 相关方法源码分析 ArrayList简介: java.util.ArrayList 是我们最常用的一个类,ArrayList ...

Docker:安装部署RabbitMQ

前言 今天原本想讲解SpringBoot集成RabbitMQ的,临近开始写时才发现家里的电脑根本没有安装RabbitMQ呀.这下只好利用已有的阿里云服务器,直接Docker安装一下了,顺道记录下,算是 ...

KindEditor编辑器使用

KindEditor使用 1)kindeditor默认模式调用 link rel="stylesheet" href="./KindEditor/themes/d ...

Unity3d中使用assetbundle

1.导出assetbundle: ①单个资源导出成assetbundle: ②多个资源导出成一个assetbundle: 2.读取assetbundle: ①加载到内存: ②解压为具体资源. 1.导出 ...

在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决

在java.ext.dirs中使用环境变量导致crontab执行不成功的问题及解决 Table of Contents 1. java.ext.dirs的使用和环境变量 2. 问题:在crontab中 ...

leetcode85 Maximal Rectangle

思路: 分别按行拆分后将这一行之前的每列叠加起来,然后使用leetcode84的思路计算. 实现: # ...

[转]Git之忽略文件(ignore file)

原文链接: .gitignore 配置文件用于配置不需要加入版本管理的文件,配置好该文件可以为 ...

ASP.NET MVC网站学习问题积累(一)

最近工作压力比较大,不得已开始自学C#.同时网站开发业务开展迫在眉睫,只能先从ASP.NET学起.回想一下,连C#和ASP.NET的关系都没有明白,就被赶鸭子上架了...我觉得这将是我工作以来最具有戏 ...

(责任编辑:IT教学网)

更多

推荐网络创业文章