最小化 systemd 启动需要什么才能在虚拟控制台上启动 getty?

最小化 systemd 启动需要什么才能在虚拟控制台上启动 getty?

对于 SysV init,我需要/etc/inittab重新生成 getty 条目、/sbin/init二进制文件、shell 的二进制文件和共享库、loginPAM getty/security/shadow 内容以及一些设备文件。

因为upstart我需要几乎相同的要求,但不是/etc/inittab,我在 下有一些*.conf文件/etc/init:一个 *.conf ,用于start on startup设置运行级别telinit,以及一个 *.conf ,用于每个getty在适当的运行级别上在该 tty 上启动/重生的 tty 。

我需要什么配置和二进制文件systemd init

我找到的所有文档似乎都集中在如何使用已安装的系统来启动和停止服务。

从运行中复制的最小文件列表(内核/initrd 除外)或者软呢帽安装就可以了,但我似乎找不到有关 的那种信息systemd


我想知道的是,对于systemd,需要哪些文件以及它们必须包含什么,才能在 initramfsswitch_root调用systemd /sbin/init.


upstart二进制文件和两个文件的示例*.conf

文件/etc/init/whatever.conf

启动时开始
发出运行级别
任务
脚本
  远程初始化2
结束脚本

文件/etc/init/tty1.conf

从运行级别开始 [12345]
重生
执行 /sbin/agetty -8 --noclear 38400 tty1 linux

示例sysvinit,二进制文件和 1 个名为 的conf 文件/etc/inittab

id:2:初始化默认值:
c1:12345:respawn:/sbin/agetty 38400 tty1 linux

现在我正在寻找systemd同等的东西。

我假设某处至少*.service需要 1 个文件,其中一个[Service]条目包含ExecStart=-/sbin/agetty --noclear %I linuxand Restart=always,但还需要什么?

答案1

首先,systemd不是传统的unix init。 Systemd 的功能要多得多,因此比较两者有点不公平。

要回答这个问题,似乎需要一些二进制文件和以下配置文件:

/usr/lib/systemd/system/default.target
/usr/lib/systemd/system/basic.target
/usr/lib/systemd/system/sysinit.target
/usr/lib/systemd/system/getty.target
/usr/lib/systemd/系统/[电子邮件受保护]
/usr/lib/systemd/system/console-getty.service

然后发出创建这些符号链接:systemctl enable console-getty.service [email protected]

/etc/systemd/system/default.target.wants/[电子邮件受保护]-> /lib/systemd/system/getty@service
/etc/systemd/system/getty.target.wants/console-getty.service -> /lib/systemd/system/console-getty.service

笔记:要利用systemd的特殊功能来动态启动、按+agetty时按需启动等,看来您还必须至少有这两个文件:AltF3

/etc/systemd/logind.conf
/lib/systemd/系统/[电子邮件受保护]

其中[email protected]是 的符号链接[email protected]

配置文件内容:

除了标记 和 (可能)之外, default.target, getty.target,文件可以为空。sysinit.target[Unit]Description=xxx

basic.target还包含依赖信息:

[单元]
描述=基本系统
需要=sysinit.target
Wants=sockets.targettimers.targetpaths.targetslices.target
After=sysinit.targetsockets.targettimers.targetpaths.targetslices.target

我不确定是否需要对不作为文件存在的目标的引用。它们被描述在systemd.special(7)手册页。


console-getty.service: (控制台上agetty的特殊情况)

[单元]
描述=控制台 Getty
After=systemd-user-sessions.service plymouth-quit-wait.service
之前=getty.target

[服务]
ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
类型=空闲
重新启动=始终
重启秒=0
UtmpIdentifier=缺点
TTYPath=/dev/console
TTY重置=是
TTYV挂断=是
KillMode=进程
忽略SIGPIPE=否
发送SIGHUP=是

[安装]
WantedBy=getty.target

[email protected]:(除控制台外所有 getty 服务的通用配置)

[单元]
描述=%I 上的 Getty
After=systemd-user-sessions.service plymouth-quit-wait.service
之前=getty.target
忽略隔离=是
条件路径存在=/dev/tty0

[服务]
ExecStart=-/sbin/agetty --noclear %I $TERM
类型=空闲
重新启动=始终
重启秒=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTY重置=是
TTYV挂断=是
TTYVTDisallocate=否
KillMode=进程
忽略SIGPIPE=否
发送SIGHUP=是

[安装]
WantedBy=getty.target
默认实例=tty1

最后,您可能需要一些特殊的二进制文件(我还没有尝试哪些是至关重要的):

/lib/systemd/systemd (/sbin/init 通常指向此)
/lib/systemd/systemd-logind
/lib/systemd/systemd-cgroups-agent
/lib/systemd/systemd-用户会话
/lib/systemd/systemd-vconsole-setup
/lib/systemd/systemd-update-utmp
/lib/systemd/systemd-sleep
/lib/systemd/systemd-sysctl
/lib/systemd/systemd-initctl
/lib/systemd/systemd-回复密码
/lib/systemd/systemd-ac-power
/lib/systemd/systemd-activate
/lib/systemd/systemd-背光
/lib/systemd/systemd-binfmt
/lib/systemd/systemd-bootchart
/lib/systemd/systemd-bus-proxyd
/lib/systemd/systemd-coredump
/lib/systemd/systemd-cryptsetup
/lib/systemd/systemd-fsck
/lib/systemd/systemd-主机名
/lib/systemd/systemd-journald
/lib/systemd/systemd-journal-gatewayd
/lib/systemd/systemd-journal-remote
/lib/systemd/systemd-localed
/lib/systemd/systemd-machined
/lib/systemd/systemd-modules-load
/lib/systemd/systemd-multi-seat-x
/lib/systemd/systemd-networkd
/lib/systemd/systemd-networkd-wait-online
/lib/systemd/systemd-quotacheck
/lib/systemd/systemd-随机种子
/lib/systemd/systemd-readahead
/lib/systemd/systemd-remount-fs
/lib/systemd/systemd-resolved
/lib/systemd/systemd-rfkill
/lib/systemd/systemd-shutdown
/lib/systemd/systemd-shutdownd
/lib/systemd/systemd-socket-proxyd
/lib/systemd/systemd-timedated
/lib/systemd/systemd-timesyncd
/lib/systemd/systemd-udevd
/lib/systemd/systemd-update-done

总结一下systemd的启动过程,我认为它的工作原理是这样的:

  1. systemd 定位basic.target(或所有*.target文件?)
  2. 依赖项根据和配置文件部分中的WantedBy=Wants=Before=After=... 指令来解析。[Install]*.service*.target
  3. *.service应该启动的服务(不是“特殊”服务),有一个[Service]带有指令的部分ExecStart=,指出要启动的可执行文件。

答案2

systemd当您切换到终端时,会自动创建一个 getty,最多可达一定的最大数量。默认值为 6(因此您会自动获得 alt+f1 到 alt+f6 的 getty)。如果您想更改此参数,您可以编辑/etc/systemd/logind.conf将参数更改NAutoVTs为其他数字(最多 12)

如果您希望生成 getty,即使您不手动切换,您也可以向该目录添加符号链接:/usr/lib/systemd/system/[email protected]/etc/systemd/system/getty.target.wants/

ln -sf /usr/lib/systemd/system/[email protected] /etc/systemd/system/getty.target.wants/[email protected]

这将导致getty.target需要再提供一项getty@服务。目标是需要生成的服务的集合,替换支持依赖项的运行级别。默认目标取决于getty.target

参见ArchWiki 中的 systemd 常见问题解答

编辑: 我又研究了一些文档

启动时,systemd守护进程会加载目标中的所有系统default及其依赖项。目标由文件定义

/etc/systemd/system/default.target
/usr/lib/systemd/system/default.target

目标具有由目录中的符号链接指定的附加服务列表

/etc/systemd/system/default.target.wants
/usr/lib/systemd/system/default.target.wants

/etc版本覆盖/usr/lib.仅需要其中一个文件.target,而不需要任何目录

getty只是可以由 init 脚本运行的服务之一。在我检查的发行版(fedora、arch)中,getty以两种不同的方式运行:

  1. 由每个终端的特定脚本启动(链接到其中的文件/usr/lib/systemd/system/[email protected]tty 名称被替换为systemd链接文件名中的
  2. logind当用户切换到虚拟终端时,根据需要自动启动(类似于旧的inetd仅在请求到达时启动服务的方式)。logind是随 一起分发的不同守护进程systemd,并从文件中读取其配置/etc/systemd/logind.conf

希望这令人满意。

答案3

经过一些实验,我发现一对目标服务就足以启动。复制自emergency.service

[Unit]
DefaultDependencies=no
Description=shell.service: Console and Login

[Service]
Environment=HOME=/root
WorkingDirectory=-/root
ExecStart=-/usr/lib/systemd/systemd-sulogin-shell
ExecStartPost=/usr/bin/openvt -f -c 16 agetty tty16
ExecStartPost=/usr/bin/openvt -f -c 17 -- agetty -p tty17
ExecStartPost=/usr/bin/openvt -f -c 18 -- agetty -p -a USER tty18
Type=idle
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
#KillMode=process
KillMode=control-group
IgnoreSIGPIPE=no
SendSIGHUP=yes

用于测试:将发行版的单元目录重命名为/lib/systemd/systemDEACT是一种简单但彻底的方法,可以将单元/单元文件的数量从 200 个减少到 10 个;还是有一些假的:

  UNIT                    LOAD      ACTIVE     SUB       DESCRIPTION
  dev-sda3.device         loaded    activating tentative /dev/sda3
  -.mount                 loaded    active     mounted   Root Mount
  tmp.mount               loaded    active     mounted   /tmp
  init.scope              loaded    active     running   System and Service Manager
  io.service              loaded    inactive   dead      io: usbhid kmod for keyboard
  remount.service         loaded    inactive   dead      remount: rw for / and tmpfs for /tmp
  shell.service           loaded    active     running   shell.service: Console and Login
  -.slice                 loaded    active     active    Root Slice
  system.slice            loaded    active     active    System Slice
* systemd-journald.socket not-found inactive   dead      systemd-journald.socket
* local-fs-pre.target     not-found inactive   dead      local-fs-pre.target
* local-fs.target         not-found inactive   dead      local-fs.target
  mini.target             loaded    active     active    "mini": Minimal Boot and Shell
* swap.target             not-found inactive   dead      swap.target
* umount.target           not-found inactive   dead      umount.target

在旁边shell.service(见顶部)我做了一个remount.serviceio.service;这modprobe usbhid对于我的(任何?)USB 键盘至关重要。重新挂载服务需要与 arch 的 initrd 脚本中的 fsck 同步以进行重新挂载,并与 tmp.mount 进行同步/tmp。我还必须找出将其rw正确放置在 KCL 上的位置...同时,我[OK]在启动时从两个一次性和一个闲置的服务。

依赖树是:

mini.target
* |-io.service
* |-remount.service
* `-shell.service

由于我remount与 KCL 的冗余/冲突并且io只是执行modprobe usbhid(也可以通过ExecStart...in完成shell.service),这只是一个目标/服务对。default.target如果不添加systemd.unit=mini.target内核 CL,请加上链接。

我花了几个小时追逐暂定的 dev-sdaX.device(唯一的,根分区);现在我认为这已经是正常的一半了。

-.mount和是内在的-.slice并且init.scope有意义。

tmp.mount我认为是在 中生成的/run

Journald not-found、local-fs、swap 和 umount 单元似乎不会损害 systemd;与--state loaded他们没有显示。它们可能应该被创建为第一个附加单元。但是如何定义local-fs根分区何时已经从 initrd 检查过呢?可以用 initrd 启动吗最小的

systemctl status也是最小的。有一个切片,但只有一个(没有 user-X 切片):

* archlinux
    State: running
     Jobs: 0 queued
   Failed: 0 units
    Since: Fri 2021-10-01 15:24:16 UTC; 3min 2s ago
   CGroup: /
           |-init.scope 
           | `-1 /sbin/init arch\x5cvmlinuz-linux
           `-system.slice 
             `-shell.service 
               |-215 /usr/lib/systemd/systemd-sulogin-shell
               |-219 bash
               |-220 agetty tty16
               |-222 agetty -p tty17
               |-225 agetty -p -a USER tty18
               `-238 systemctl status

KillMode可以控制 shell.service 内进程发生的情况。对应的ps axf是:

    1 ?        Ss     0:00 /sbin/init arch\vmlinuz-linux
  215 tty1     Ss     0:00 /usr/lib/systemd/systemd-sulogin-shell
  219 tty1     S      0:00  \_ bash
  245 tty1     R+     0:00      \_ ps axf
  246 tty1     S+     0:00      \_ tail -8
  220 tty16    Ss+    0:00 agetty tty16
  222 tty17    Ss+    0:00 agetty -p tty17
  225 tty18    Ss+    0:00 agetty -p -a USER tty18

sagetty没有父母 - 感谢openvt? - 但 PID1/init/systemd 仍然跟踪 pid。我能够shell.service用不同的KillModes 重新启动。

不建议在 sulogin-shell 上使用Actrl-D或......exit

我怎样才能阻止这一切呢?

之后,激进的目录重命名reboot命令“无法与 init 守护进程对话”等等。reboot.service具有操作(不重新启动,不立即重新启动)的(副本)reboot-force是最直接的出路,并且足以用于此测试启动(没有日志运行等)。 Sysvinit 关闭也不是很优雅,也不是很快。systemctl start reboot然后执行 PID 信号发送和终止,以及sync(我猜),但没有其他命令关闭。这将是一个“最终”或“关闭”目标,从那里您可以转到CPUrebootpoweroffhalt带或不带 shutdown-initramfs。


因此systemd可以在没有journald、udevd 和dbus 以及所有这些单元文件和--user实例的情况下启动和运行(和停止!)。但是很难“超级屏蔽”(即消失)这 200 个发行版单元,而且仍然存在一些内置单元和内置逻辑的痕迹。

长话短说: emergency.target, DefaultDependencies=no,openvt

相关内容