agetty深入分析

前言:
  了解agetty对于我们使用和安全设置你的系统意义重大,通过本文可以了解登录管理机制、以及交互环境的行为干预等。
 但是这个主题实际内容还是比较多的,知识点很多,又怕有遗漏,又怕写的又臭又长。网上其他人也有介绍,但是很多是蜻蜓点水,一带而过,我尽量是写就写好吧,尽量实验为主,但是确实很费心。有不足还请谅解。

实验环境

我是在linux ,centos,3.10版本内核上做的测试,所以主要针对小红帽的centos做讲解
[root@aozhejin2 /usr/local/src]$cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
[root@aozhejin2 /usr/local/src]$uname -r
3.10.0-1160.62.1.el7.x86_64

[root@aozhejin2 ~]$systemd-analyze
Startup finished in 764ms (kernel) + 1.598s (initrd) + 30.920s (userspace) = 33.283s


一、what is agetty?

      agtty 是 管理员程序/命令,它是linux版本getty(),用来设置终端类型、模式、速度和termios(里面包含各种选项比如自动登录等)、ldisc等。
     它被init程序调用 它是 bios-kernelboot-init-getty-login-shell系列中的第三个进程(前面mbr、grub等先忽略)。 最终将用户与 Linux 系统连接起来。agetty读取用户的loginname并以loginname作为参数调用登录命令。在读取名称时,agetty会尝试使系统适应正在使用的设备的速度和类型。您必须指定一个端口,agetty将在/dev目录 中搜索该端口您可以使用 -,在这种情况下agetty从标准输入读取。您还必须指定baudrate,它可以是逗号分隔的速率列表,agetty 将逐步执行。或者,您可以指定term,它用于覆盖 TERM 环境变量。
    

[root@aozhejin2 /usr/lib/systemd/system]$agetty -
CentOS Linux 7 (Core)
Kernel 3.10.0-1160.62.1.el7.x86_64 on an x86_64
aozhejin2 login: root
....

 

Linux 系统运行后可以通过三种方式登录:
1.在本地通过字符模式连接。这可能是系统控制台、伪终端(系统控制台访问)或连接(可能通过调制解调器)到串行线路的真实终端。
   调制解调器部分可参看 https://en.wikipedia.org/wiki/RS-232 也就是串口(ttyS0等),在嵌入式设备等还是有广泛的应用
  要使用串行控制台,只需在内核命令行上使用 console=ttyS0,systemd 会自动为您启动agetty
2.通过图形界面在本地或远程。
3.通过某些协议(如 rsh、ssh 或 telnet)进行远程访问(我这里是通过跳板机登录到实验环境)。


对于本地非图形界面:
1.对于任何本地非图形界面,运行程序 /sbin/agetty(或有时 /sbin/mingetty等,看你的系统)。
   1) 按照sysv方式:
       getty 的启动是从/etc/inittab中针对 SysV 版本的 init 完成的,并由 Upstart 中的启动配置文件(每个终端一个)完成。
   2)按照systemd方式:
        本机采用这种方式,在 systemd 中,每个 tty 设备都会指向 getty@.service 服务的符号链接表示 。
2. getty(或agetty等) 在 stdout 设备(一般是屏幕)上发出登录提示(或等待调制解调器上的连接,然后发出登录提示)。
3.输入用户名后,getty(agetty等) 执行 /bin/login程序。login程序 读取并验证密码,然后对 /etc/passwd 中为登录用户指定的 shell 程序执行 exec。
4.当用户注销时,getty(agetty) 检测进程终止并重置终端以建立新连接。


注意登录管理模式:
1.SysV(也称 System v) init模式最典型的是采用6个run-levels机制。
2.Upstart 是用来替代SysV init 模式而开发的,但是现代流行的系统中已不多见这种方式。
3.systemd采用是服务管理机制,它替换SysV init和Upstart 来初始化启动过程。RHEL6采用的是Upstart 方式,RHEL6之前用的是SysVinit
    systemd是红帽7和Ubuntu(15.04)之后采用的方式(centos6上你可以看下,处理方式还是不一样的)。
    这个几种模式不了解,你也无从谈起安全防范和攻击等事件。
本机采用的systemd,而systemd有两种在文本控制台上显示登录提示
1. getty@.service(即非串行TTY)负责虚拟终端(VT) 登录提示,即显示在/dev/tty1和类似设备中的 VGA 屏幕上的提示。

[root@aozhejin2 ~]$locate getty@.service
/usr/lib/systemd/system/getty@.service   

   如果我们想建多个,则cp 这个文件成 getty@tty2.service、getty@tty3.service等

2.serial-getty@.service负责所有其他终端,包括/dev/ttyS0等串行端口

[root@aozhejin2 ~]$locate serial-getty@.service
/usr/lib/systemd/system/serial-getty@.service

另外一种是 console
3.console-getty.service,/dev/console 和 container-getty@.service 实例

[root@aozhejin2 ~]$locate console-getty.service
/usr/lib/systemd/system/console-getty.service
[root@aozhejin2 ~]$cat /usr/lib/systemd/system/console-getty.service
[Unit]
Description=Console Getty
Documentation=man:agetty(8)
After=systemd-user-sessions.service plymouth-quit-wait.service
ConditionPathExists=/dev/console
After=rc-local.service getty-pre.target
Before=getty.target
[Service]
ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=cons
TTYPath=/dev/console
TTYReset=yes
TTYVHangup=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
[Install]
WantedBy=getty.target

在内核控制台*getty@.service上实例化都由各自的一些生成器来生成(他们用于启用 getty 实例的生成器)

[root@aozhejin2 ~]$ls /usr/lib/systemd/system-generators
kdump-dep-generator.sh     rpc-pipefs-generator          systemd-efi-boot-generator  systemd-hibernate-resume-generator  systemd-sysv-generator
lvm2-activation-generator  systemd-cryptsetup-generator  systemd-fstab-generator     systemd-rc-local-generator
nfs-server-generator       systemd-debug-generator       systemd-getty-generator     systemd-system-update-generator

 

二、调用agetty

    首先看下systemd运行情况,注意这里是通过systemd在管理相关服务包括agetty的启动等

[root@aozhejin2 ~]$systemctl list-units   | egrep -i "tty|login"
sys-devices-platform-serial8250-tty-ttyS0.device loaded active plugged     /sys/devices/platform/serial8250/tty/ttyS0
sys-devices-platform-serial8250-tty-ttyS1.device loaded active plugged     /sys/devices/platform/serial8250/tty/ttyS1
sys-devices-platform-serial8250-tty-ttyS2.device loaded active plugged     /sys/devices/platform/serial8250/tty/ttyS2
sys-devices-platform-serial8250-tty-ttyS3.device loaded active plugged     /sys/devices/platform/serial8250/tty/ttyS3
getty@tty1.service                               loaded active running      Getty on tty1
getty@tty6.service                               loaded active running      Getty on tty6
systemd-logind.service                           loaded active running      Login Service
system-getty.slice                               loaded active active       system-getty.slice
getty.target                                     loaded active active       Login Prompts

  查看进程运行情况

[root@aozhejin2 /usr/lib/systemd/system]$ps -ef | grep agetty
root 870 1 0 2022 tty1 00:00:00 /sbin/agetty --noclear tty1 linux
root 11148 1 0 Mar29 tty6 00:00:00 /sbin/agetty --noclear tty6 linux
man getty手册以下内容开头:
 getty打开一个 tty设备,提示输入登录名并调用 /bin/login 命令。它通常由 init(8)调用。
 请注意 getty、 agetty、 fgetty和 mingetty只是getty的不同实现。
 init运行最显着的效果是它产生一个登录到每个LINUX虚拟控制台。显示此登录的是上面inittab行中指定的getty(system v方式)
(或有时是 mingetty)命令。输入登录名后,agetty将调用
/bin/login程序,然后提示用户输入密码。 登录程序执行一个 shell。当 shell 死亡时(由于用户退出会话)getty只是重建。

https://man7.org/linux/man-pages/man8/agetty.8.html
        agetty 打开一个 tty设备,提示输入登录名并调用/bin/login 命令。它通常由init (8) 调用。

       agetty有几个非标准功能,可用于硬连线和拨入线:
       • 使 tty 设置适应奇偶校验位并擦除、终止、读取登录时的行尾字符和大写字符姓名。该程序可以处理 7 位字符,包括偶数、奇数、
           无或空格奇偶校验,以及无奇偶校验的 8 位字符。
           识别以下特殊字符:Control-U (杀); DEL 和退格键(擦除);回车和换行进给(行尾)。另请参阅--erase-chars和
           --kill-chars选项。
       • 可选地从 CONNECT 消息中推断出波特率由与 Hayes(tm) 兼容的调制解调器生产。
       • 可选择不挂机打开的线路(对回调应用程序有用)。
       • 可选择不显示/etc/issue的内容文件。
       • 可选择显示替代问题文件或目录而不是/etc/issue或/etc/issue.d。
       • 可选择不要求登录名。
       • 可选择调用非标准登录程序而不是 /bin/login。
       • 可选择打开硬件流控制。
       • 可选择强制线路为本地线路,无需载波检测。
       该程序不使用/etc/gettydefs (System V) 或/etc/gettytab (SunOS 4) 文件。


  /sbin/agetty是一个二进制程序  

[root@aozhejin2 /usr/lib/systemd/system]$file /sbin/agetty
/sbin/agetty: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=3b10f282c75c8419ff4abb5738389e7c4cb69bc0, stripped

/bin/login

[root@aozhejin2 /usr/lib/systemd/system]$stat /bin/login
  File: ‘/bin/login’
  Size: 37248         Blocks: 80         IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 134327918   Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-03-29 08:17:15.942772765 +0800
Modify: 2021-02-03 00:31:53.000000000 +0800
Change: 2021-09-23 10:26:40.773848683 +0800
 Birth: -

采用的是sysv版本的

[root@aozhejin2 /usr/lib/systemd/system]$file /bin/login
/bin/login: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 

源码: https://github.com/util-linux/util-linux/blob/master/login-utils/login.c (util-linux工具套件)

下面在agetty.c 和login.c中都会调用get_terminal_name得到,但是它只验证而已,他们最终会调用内核定义的三个宏。

/sbin/agetty
main{
   parse_args(argc, argv, &options);
}
parse_args(){
...   
  if (strcmp(op->tty, "-") == 0) {
        op->tty_is_stdin = 1;
        int fd = get_terminal_name(NULL, &op->tty, NULL);
        if (fd < 0) {
            log_warn(_("could not get terminal name: %d"), 
               fd);  //不能得到终端的名称
        }
    }
....
}

// /bin/login
static void init_tty(struct login_context *cxt){
get_terminal_name(&cxt->tty_path, &cxt->tty_name, &cxt->tty_number);
}
https://kernel.googlesource.com/pub/scm/utils/util-linux/util-linux/+/master/lib/ttyutils.c

 

  agetty.c中关于tty处理部分
/* Set up tty as stdin, stdout & stderr. */
static void open_tty(const char *tty, struct termios *tp, struct options *op)
{
   ....
}
//默认tty名是tty1


  /etc/systemd/logind.conf  
 这个配置文件很重要的一个作用就是控制终端的实例数量。
 
centos7开始可以在 /etc/systemd/logind.conf 修改,文件/etc/systemd/logind.conf_是服务的配置文件systemd-logind, 服务管理命令为 systemd-logind.service  通过  cat /usr/lib/systemd/system/systemd-logind.service  查看启动服务文件,同时使用

systemctl restart systemd-logind  进行服务重启等。

[root@aozhejin2 ~]$file /usr/lib/systemd/systemd-logind
/usr/lib/systemd/systemd-logind: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),

[root@aozhejin2 ~]$cat /etc/systemd/logind.conf
#  This file is part of systemd.#显示的值是编译到可执行文件中的默认值
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
# See logind.conf(5) for details.
[Login]
#NAutoVTs=6   //终端可以有几个,比如只能有3个终端,则设置为3
#ReserveVT=6  //要保留的VT,列表
#KillUserProcesses=no
#KillOnlyUsers=
#KillExcludeUsers=root
#InhibitDelayMaxSec=5
#下面是电源管理命令,控制比如闲置怎么处理、合上盖子怎么处理等
#HandlePowerKey=poweroff
#HandleSuspendKey=suspend
#HandleHibernateKey=hibernate
#HandleLidSwitch=suspend   #合上笔记本还能运行,那么就启用它,当然它的值还可以是ignore
#HandleLidSwitchDocked=ignore
#PowerKeyIgnoreInhibited=no
#SuspendKeyIgnoreInhibited=no
#HibernateKeyIgnoreInhibited=no
#LidSwitchIgnoreInhibited=yes
#IdleAction=ignore
#IdleActionSec=30min
#RuntimeDirectorySize=10%
#RemoveIPC=no
#UserTasksMax=

 查看下 systemd-logind 启动情况

[root@aozhejin2 ~]$systemctl status systemd-logind
● systemd-logind.service - Login Service
   Loaded: loaded (/usr/lib/systemd/system/systemd-logind.service; static; vendor preset: disabled)
   Active: active (running) since Wed 2023-03-29 17:45:37 CST; 23h ago
     Docs: man:systemd-logind.service(8)
           man:logind.conf(5)
           http://www.freedesktop.org/wiki/Software/systemd/logind
           http://www.freedesktop.org/wiki/Software/systemd/multiseat
 Main PID: 9448 (systemd-logind)
   Status: "Processing requests..."
    Tasks: 1
   Memory: 3.4M
   CGroup: /system.slice/systemd-logind.service
           └─9448 /usr/lib/systemd/systemd-logind

Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 57949 of user root.
Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 1 of user root.
Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 1057 of user root.
Mar 29 18:08:07 aozhejin2 systemd-logind[9448]: Removed session 57949.
...

我们一下这个进程会打开哪些文件

[root@aozhejin2 ~]$lsof -p 9448
COMMAND    PID USER   FD      TYPE             DEVICE SIZE/OFF      NODE NAME
systemd-l 9448 root  cwd       DIR              253,0     4096       128 /
systemd-l 9448 root  rtd       DIR              253,0     4096       128 /
systemd-l 9448 root  txt       REG              253,0   639832 402655657 /usr/lib/systemd/systemd-logind
systemd-l 9448 root  mem       REG              253,0    61560 269462479 /usr/lib64/libnss_files-2.17.so
systemd-l 9448 root  mem       REG              253,0    19896 268991954 /usr/lib64/libattr.so.1.1.0
systemd-l 9448 root  mem       REG              253,0    19248 268820392 /usr/lib64/libdl-2.17.so
systemd-l 9448 root  mem       REG              253,0   402384 268730267 /usr/lib64/libpcre.so.1.2.0
systemd-l 9448 root  mem       REG              253,0  2156592 268633378 /usr/lib64/libc-2.17.so
systemd-l 9448 root  mem       REG              253,0   142144 269462486 /usr/lib64/libpthread-2.17.so
systemd-l 9448 root  mem       REG              253,0    88720 268633409 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
systemd-l 9448 root  mem       REG              253,0    37064 268991961 /usr/lib64/libacl.so.1.1.0
systemd-l 9448 root  mem       REG              253,0    20048 268991956 /usr/lib64/libcap.so.2.22
systemd-l 9448 root  mem       REG              253,0    43712 269462491 /usr/lib64/librt-2.17.so
systemd-l 9448 root  mem       REG              253,0   155744 268633517 /usr/lib64/libselinux.so.1
systemd-l 9448 root  mem       REG              253,0   163312 281915295 /usr/lib64/ld-2.17.so
systemd-l 9448 root    0r      CHR                1,3      0t0      1028 /dev/null
systemd-l 9448 root    1u     unix 0xffff8a6de94f5500      0t0 640028488 socket
systemd-l 9448 root    2u     unix 0xffff8a6de94f5500      0t0 640028488 socket
systemd-l 9448 root    3u     unix 0xffff8a69cc137700      0t0 640029131 socket
systemd-l 9448 root    4u  a_inode               0,10        0      8534 [eventpoll]
systemd-l 9448 root    5u  a_inode               0,10        0      8534 [timerfd]
systemd-l 9448 root    6r      REG               0,18     4096     28661 /sys/devices/virtual/tty/tty0/active
systemd-l 9448 root    7u  a_inode               0,10        0      8534 [signalfd]
systemd-l 9448 root    8u  netlink                         0t0 640029133 KOBJECT_UEVENT
systemd-l 9448 root    9u  netlink                         0t0 640029134 KOBJECT_UEVENT
systemd-l 9448 root   10u  netlink                         0t0 640029135 KOBJECT_UEVENT
systemd-l 9448 root   11u  netlink                         0t0 640029136 KOBJECT_UEVENT
systemd-l 9448 root   12u     unix 0xffff8a69cc135500      0t0 640029137 socket
systemd-l 9448 root   13u  a_inode               0,10        0      8534 [timerfd]
systemd-l 9448 root   14u      CHR              13,64      0t0      1149 /dev/input/event0
systemd-l 9448 root   15r     FIFO               0,20      0t0 640056595 /run/systemd/sessions/57961.ref
systemd-l 9448 root   16u      CHR                4,6      0t0      1048 /dev/tty6
systemd-l 9448 root   17r     FIFO               0,20      0t0 640217015 /run/systemd/sessions/57980.ref
systemd-l 9448 root   18r     FIFO               0,20      0t0 641501820 /run/systemd/inhibit/1.ref

我们跟踪一下

[root@aozhejin2 ~]$strace -e open lsof -p 9448
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 open("/proc/filesystems", O_RDONLY) = 3 open("/dev/null", O_RDWR) = 3 open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 open("/", O_RDONLY) = 3 open("/proc/98712/fdinfo/3", O_RDONLY) = 4 open("/proc/mounts", O_RDONLY) = 3 .... open("/proc/126121/stat", O_RDONLY) = 4 open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 4 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4 open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 4 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 4 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 4 systemd-l 9448 root cwd DIR 253,0 4096 128 / systemd-l 9448 root rtd DIR 253,0 4096 128 / systemd-l 9448 root txt REG 253,0 639832 402655657 /usr/lib/systemd/systemd-logind systemd-l 9448 root mem REG 253,0 61560 269462479 /usr/lib64/libnss_files-2.17.so systemd-l 9448 root mem REG 253,0 19896 268991954 /usr/lib64/libattr.so.1.1.0 systemd-l 9448 root mem REG 253,0 19248 268820392 /usr/lib64/libdl-2.17.so systemd-l 9448 root mem REG 253,0 402384 268730267 /usr/lib64/libpcre.so.1.2.0 systemd-l 9448 root mem REG 253,0 2156592 268633378 /usr/lib64/libc-2.17.so systemd-l 9448 root mem REG 253,0 142144 269462486 /usr/lib64/libpthread-2.17.so systemd-l 9448 root mem REG 253,0 88720 268633409 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 systemd-l 9448 root mem REG 253,0 37064 268991961 /usr/lib64/libacl.so.1.1.0 systemd-l 9448 root mem REG 253,0 20048 268991956 /usr/lib64/libcap.so.2.22 systemd-l 9448 root mem REG 253,0 43712 269462491 /usr/lib64/librt-2.17.so systemd-l 9448 root mem REG 253,0 155744 268633517 /usr/lib64/libselinux.so.1 systemd-l 9448 root mem REG 253,0 163312 281915295 /usr/lib64/ld-2.17.so systemd-l 9448 root 0r CHR 1,3 0t0 1028 /dev/null systemd-l 9448 root 1u unix 0xffff8a6de94f5500 0t0 640028488 socket systemd-l 9448 root 2u unix 0xffff8a6de94f5500 0t0 640028488 socket systemd-l 9448 root 3u unix 0xffff8a69cc137700 0t0 640029131 socket systemd-l 9448 root 4u a_inode 0,10 0 8534 [eventpoll] systemd-l 9448 root 5u a_inode 0,10 0 8534 [timerfd] systemd-l 9448 root 6r REG 0,18 4096 28661 /sys/devices/virtual/tty/tty0/active systemd-l 9448 root 7u a_inode 0,10 0 8534 [signalfd] systemd-l 9448 root 8u netlink 0t0 640029133 KOBJECT_UEVENT systemd-l 9448 root 9u netlink 0t0 640029134 KOBJECT_UEVENT systemd-l 9448 root 10u netlink 0t0 640029135 KOBJECT_UEVENT systemd-l 9448 root 11u netlink 0t0 640029136 KOBJECT_UEVENT systemd-l 9448 root 12u unix 0xffff8a69cc135500 0t0 640029137 socket systemd-l 9448 root 13u a_inode 0,10 0 8534 [timerfd] systemd-l 9448 root 14u CHR 13,64 0t0 1149 /dev/input/event0 systemd-l 9448 root 15r FIFO 0,20 0t0 640056595 /run/systemd/sessions/57961.ref systemd-l 9448 root 16u CHR 4,6 0t0 1048 /dev/tty6 systemd-l 9448 root 17r FIFO 0,20 0t0 640217015 /run/systemd/sessions/57980.ref systemd-l 9448 root 18r FIFO 0,20 0t0 641501820 /run/systemd/inhibit/1.ref --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=98713, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---

注意:  上面黄色显示的tty0代表当前,你可以通过读取 /sys/devices/virtual/tty/tty0/active 得到当前的tty
具体可以参看看 https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-tty
我的另一篇博文也有对于查看当前tty的阐述,
https://www.cnblogs.com/aozhejin/p/17253982.html

 

我们继续分析下/sbin/init

[root@aozhejin2 ~]$ps xawf -eo pid,user,cgroup,args
   PID USER     CGROUP                      COMMAND
  ......
 1144 root     11:pids:/lxc/mylxc,10:memor  \_ /sbin/init
  1182 root     11:pids:/user.slice,10:memo      \_ /usr/lib/systemd/systemd-logind
  1184 dbus     11:pids:/user.slice,10:memo      \_ /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
  1188 root     11:pids:/user.slice,10:memo      \_ /usr/sbin/crond -n
  1369 root     11:pids:/user.slice,10:memo      \_ /sbin/dhclient -1 -q -lf /var/lib/dhclient/dhclient--eth0.lease -pf /var/run/dhclient-eth0.pid -H mylxc.node eth0
  1444 root     11:pids:/user.slice,10:memo      \_ /usr/sbin/sshd -D
  1445 root     11:pids:/user.slice,10:memo      \_ /usr/sbin/rsyslogd -n
  1894 root     11:pids:/user.slice,10:memo      \_ login -- root
  2153 root     11:pids:/user.slice,10:memo      |   \_ -bash
  2151 root     11:pids:/user.slice,10:memo      \_ /usr/lib/systemd/systemd-journald
....

显示键盘布局和系统本地化信息

[root@aozhejin2 ~]$localectl
   System Locale: LANG=en_US.UTF-8
       VC Keymap: us
      X11 Layout: us

当前内核设置的

[root@aozhejin2 ~]$cat /sys/class/tty/console/active
0
/var/run/utmp文件 (登录日志)
[root@aozhejin2 ~]$cat /var/run/utmp  #不正确
[root@aozhejin2 ~]$ last -f /var/run/utmp
  root pts/9 192.168.1.3 Thu Mar 30 19:09 still logged in 
  root pts/8 192.168.1.3 Thu Mar 30 19:01 still logged in 
  root pts/7 192.168.1.3 Fri Mar 31 09:26 still logged in 
  reboot system boot 3.10.0-1160.62.1 Thu Apr 21 08:57 - 09:31 (344+00:33)
  utmp begins Thu Apr 21 08:57:37 2022

查看tty1服务...

[root@aozhejin2 ~]$systemctl status getty@tt1.service
● getty@tt1.service - Getty on tt1
   Loaded: loaded (/usr/lib/systemd/system/getty@.service; enabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:agetty(8)
           man:systemd-getty-generator(8)
           http://0pointer.de/blog/projects/serial-console.html

/usr/lib/systemd/system/getty@.service

[root@aozhejin2 ~]$cat /usr/lib/systemd/system/getty@.service
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0
[Service]
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
[Install]
WantedBy=getty.target
DefaultInstance=tty1  //默认实例是tty1

查看一下 agetty进程,启动服务文件看上面,我们看到下面的都是1进程启用的
 第二个参数 tty1,传递给agetty,main函数处理,利用parse_args、 open_tty等函数。

[root@aozhejin2 ~]$ps -ef | grep tty
root        870      1  0  2022 tty1     00:00:00 /sbin/agetty --noclear tty1 linux
root      11005  10876  0 18:08 pts/6    00:00:00 grep --color=auto tty
root     104003      1  0 Mar25 tty6     00:00:00 /sbin/agetty --noclear tty6 linux

   agetty.c 处理 termio 部分在termio_init中

/* Initialize termios settings. */
static void termio_init(struct options *op, struct termios *tp)
{
   ....
}
三、agetty的配置文件
agetty读取/etc/login.defs配置文件(参见 login.defs(5))。请注意,配置文件可能是与另一个包一起分发(通常是 shadow-utils)。
https://man7.org/linux/man-pages/man5/login.defs.5.html


  本机  /etc/login.defs(工作在pam模式下,属于shadow password套件,所以这里可以忽略)

[root@aozhejin2 /usr/local/src/stracetest]$cat /etc/login.defs
# 请注意,此配置文件中的参数控制shadow-utils组件中工具的行为. 
# 这些工具都不使用PAM机制,因此应该在其他地方配置使用PAM的实用程序(如passwd命令)。
# 了解更多信息请参考 /etc/pam.d/system-auth等. # *REQUIRED* # Directory where mailboxes reside, _or_ name of file, relative to the # home directory. If you _do_ define both, MAIL_DIR takes precedence. # QMAIL_DIR is for Qmail #QMAIL_DIR Maildir MAIL_DIR /var/spool/mail #MAIL_FILE .mail # Password控制: # PASS_MAX_DAYS 密码可以使用的最大天数 # PASS_MIN_DAYS 密码更改之间允许的最小天数. # PASS_MIN_LEN 可接受的最小密码长度。 # PASS_WARN_AGE 密码过期前发出警告的天数。 PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_MIN_LEN 5 PASS_WARN_AGE 7 # useradd 中自动选择 uid 的最小/最大值 UID_MIN 1000 UID_MAX 60000 # 系统帐户 SYS_UID_MIN 201 SYS_UID_MAX 999 # groupadd中自动gid选择的最小/最大值 GID_MIN 1000 GID_MAX 60000 # 系统帐户 SYS_GID_MIN 201 SYS_GID_MAX 999 # 如果已定义,则在删除用户时运行此命令. # 它应该删除任何at/cron/print 作业等. 由要删除的用户所有(作为第一个参数传递)。 # USERDEL_CMD /usr/sbin/userdel_local #这个文件可以不存在 # 如果useradd在RH系统上默认为用户创建主目录,我们会这样做。这个选项在useradd命令行上被-m标志覆盖。 CREATE_HOME yes # 权限掩码已初始化为此值. 如果未指定,则权限掩码将初始化为022。 UMASK 077 # 这使得userdel能够在不存在成员的情况下删除用户组。 USERGROUPS_ENAB yes #使用 SHA512 加密密码。

/etc/login.defs被定义在util-linux套件里面的下面文件中
https://kernel.googlesource.com/pub/scm/utils/util-linux/util-linux/+/master/include/pathnames.h
https://github.com/mmalecki/util-linux/blob/master/login-utils/logindefs.c 中定义
getlogindefs_bool 函数
agetty.c会调用 getlogindefs_bool("LOGIN_PLAIN_PROMPT", 0) 检测
该文件针对 shadow password(非pam认证模式)
可参看 https://help.adelielinux.org/html/admin/config.html(相关和登录有关的配置文件)

 
解析 /etc/issue(这个通常也是login banner头)

[root@aozhejin2 ~]$agetty -N8nl /bin/true -f <(sed "s@\\l@$(tty |sed 's:^/dev/::')@g" /etc/issue) -
CentOS Linux 7 (Core)
Kernepts/6 3.10.0-1160.62.1.el7.x86_64 on an x86_64

  [root@aozhejin2 ~]$cat /etc/issue
  \S
  Kernel \r on an \m

  agetty.c中 read_os_release 负责解析 S  //读取的 /etc/os-release 数据...

 

 agetty.c 中

  系统状态文件 注意事项
/etc/issue 打印登录之前的信息  
/etc/os-release /usr/lib/os-release 操作系统标识数据  
/dev/console 问题报告(if syslog(3) is not used)  
/etc/inittab /sbin/init配置文件,针对SysV-style init 守护进程 systemd使用时,不读取/etc/inittab
 /var/run/utmp    

 

四、login.c(对应/bin/login)
      我们下面做一个测试修改欢迎信息

//login.c 中设置的逻辑
main(){
...
initialize(argc, argv, &cxt); //这个函数里面调用 display_login_messages
...
} static void display_login_messages(void) { ... motd(); ... } static void motd(void) { //_PATH_MOTDFILE这个宏是在 // pathnames.h 中定义 } //pathnames.h #define _PATH_MOTDFILE "/usr/share/misc/motd:/run/motd:/etc/motd"

   修改文件之后.重新登录

[root@aozhejin2 /etc/pam.d]$cat  /etc/motd
欢迎你
root@192.168.1.2's password: 
Last login: Wed Mar 29 18:11:39 2023 from 10.129.55.19
欢迎你

 

五、PAM身份认证(这里不做介绍)
      /bin/login 会调用相关pam设置 。 基于目录的配置  /etc/pam.d/都在这里
六、我们分析下内核启动时候的调用
   E:\linux内核\linux-2.6.38.5\linux-2.6.38.5\init\main.c   内核启动入口

//汇编.S会调用这里
asmlinkage void __init start_kernel(void)
{
       //最后调用
    rest_init();
}
static noinline void __init_refok rest_init(void)
{
 //调用kernel_init 
  kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
}

//kernel_init定义
static int __init kernel_init(void * unused)
{
  /* Open the /dev/console on the rootfs, this should never fail */
    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
        printk(KERN_WARNING "Warning: unable to open an initial console.\n");
   //执行/sbin/init等程序
   init_post();
}
 //执行根文件系统下的 /sbin/init 等程序
static noinline int init_post(void)
{
    /* need to finish all async __init code before freeing the memory */
    async_synchronize_full();
    free_initmem();
    mark_rodata_ro();
    system_state = SYSTEM_RUNNING;
    numa_default_policy();


    current->signal->flags |= SIGNAL_UNKILLABLE;

    if (ramdisk_execute_command) {
        run_init_process(ramdisk_execute_command);
        printk(KERN_WARNING "Failed to execute %s\n",
                ramdisk_execute_command);
    }

    /*
     * We try each of these until one succeeds.
     *
     * The Bourne shell can be used instead of init if we are
     * trying to recover a really broken machine.
     */
    if (execute_command) {
        run_init_process(execute_command);
        printk(KERN_WARNING "Failed to execute %s.  Attempting "
                    "defaults...\n", execute_command);
    }
    run_init_process("/sbin/init");   //这里内核代码2.6、3.10等都没有变化对于这里的,但是兼容systemd等。
    run_init_process("/etc/init");
    run_init_process("/bin/init");
    run_init_process("/bin/sh");

    panic("No init found.  Try passing init= option to kernel. "
          "See Linux Documentation/init.txt for guidance.");
}

static void run_init_process(const char *init_filename)
{
    argv_init[0] = init_filename;
    kernel_execve(init_filename, argv_init, envp_init); 
}


七、关于/sbin/init

    Linux内核初始化(dmesg 命令查看内核启动日志或 /dev/kmsg,打印的都是内核调用的信息)完成后,内核调用执行程序/sbin/init。(对于 systemd来说,/sbin/init 实际上是指向另一个文件 /usr/lib/systemd/systemd 的符号链接(内核2.6、3.10、4.2、5.10等都是这样做到了先后兼容性处理,起码我看过内核源码是这样)

[root@aozhejin2 /]$readlink /sbin/init
../lib/systemd/systemd

  [root@aozhejin2 /]$file /sbin/init
  /sbin/init: symbolic link to `../lib/systemd/systemd'

//stat比较一下  /sbin/init和/usr/lib/systemd/systemd

[root@aozhejin2 /]$stat /sbin/init
File: ‘/sbin/init’ -> ‘../lib/systemd/systemd’
Size: 22 Blocks: 0 IO Block: 4096 symbolic link
Device: fd00h/64768d Inode: 268956188 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2023-03-29 13:33:50.272887394 +0800
Modify: 2022-04-11 14:50:59.063110982 +0800
Change: 2022-04-11 14:50:59.064110982 +0800
Birth: -
[root@aozhejin2 /]$stat /usr/lib/systemd/systemd
File: ‘/usr/lib/systemd/systemd’
Size: 1632960 Blocks: 3192 IO Block: 4096 regular file
Device: fd00h/64768d Inode: 402655640 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2023-03-29 13:33:50.272887394 +0800
Modify: 2022-01-14 00:54:56.000000000 +0800
Change: 2022-04-11 14:50:58.678111000 +0800

 


    查看/usr/lib/systemd/systemd这个文件是一个二进制文件

[root@aozhejin2 /]$file /usr/lib/systemd/systemd
/usr/lib/systemd/systemd: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), ....

 

 我们看下init进程和 进程号为1的进程(启动进程的情况)

[root@aozhejin2 /usr/local/src/stracetest]$ps 1
   PID TTY      STAT   TIME COMMAND
     1 ?        Ss   154:01 /usr/lib/systemd/systemd --system --deserialize 20

  [root@aozhejin2 /usr/local/src/stracetest]$ps -ef | grep /sbin/init
  root 1144 1135 0 2022 ? 00:01:21 /sbin/init

   /sbin/init配置文件为 /etc/inittab,在linux启动时候读取


     讲/sbin/init配置文件 即在解说systemd配置文件(本机采用systemd管理服务)

      init 的 systemd 版本从  /etc/systemd/system目录  和  /usr/lib/systemd/system目录读取一系列文件。这些文件中的每一个都称为“单元”,单元可以是各种类型,例如服务、目标等,如文件名后缀(.service、.target 等)所示。“服务”通常是守护进程在后台运行以执行某些系统功能
       

systemd相关  
 /usr/lib/systemd/system  systemd的服务 *.service、*.target等文件放置的目录
 /etc/systemd/system systemd本身配置文件
 /usr/lib/systemd/systemd /sbin/init指向该程序
   

 

systemd本身的配置文件放置目录

[root@aozhejin2 /]$ls /etc/systemd/system basic.target.wants default.target.wants local-fs.target.wants remote-fs.target.wants
sysinit.target.wants timers.target.wants
default.target getty.target.wants multi-user.target.wants sockets.target.wants
system-update.target.wants
systemd二进制程序放置的目录以及启动服务放置的目录

[root@aozhejin2 /]$ls -l /usr/lib/systemd/
total 7960
drwxr-xr-x. 2 root root 4096 Apr 11 2022 catalog
-rw-r--r-- 1 root root 9551 Jan 14 2022 import-pubring.gpg
drwxr-xr-x. 2 root root 47 Jan 14 2022 ntp-units.d

......
drwxr-xr-x 2 root root 29 Nov 19 2021 scripts
drwxr-xr-x. 26 root root 16384 Mar 17 08:59 system   // systemd的服务 *.service、*.target等文件放置的目录
-rwxr-xr-x 1 root root 1632960 Jan 14 2022 systemd   // systemd的二进制程序
-rwxr-xr-x 1 root root 23968 Jan 14 2022 systemd-ac-power
-rwxr-xr-x 1 root root 70168 Jan 14 2022 systemd-activate
.....
-rwxr-xr-x 1 root root 317272 Jan 14 2022 systemd-initctl
-rwxr-xr-x 1 root root 346168 Jan 14 2022 systemd-journald
-rwxr-xr-x 1 root root 384224 Jan 14 2022 systemd-localed
-rwxr-xr-x 1 root root 639832 Jan 14 2022 systemd-logind
-rwxr-xr-x 1 root root 493576 Jan 14 2022 systemd-machined
-rwxr-xr-x 1 root root 53440 Jan 14 2022 systemd-machine-id-commit
-rwxr-xr-x 1 root root 66360 Jan 14 2022 systemd-modules-load
-rwxr-xr-x 1 root root 187536 Jan 14 2022 systemd-pull
.....
-rwxr-xr-x 1 root root 150280 Jan 14 2022 systemd-shutdown
-rwxr-xr-x 1 root root 66072 Jan 14 2022 systemd-shutdownd
-rwxr-xr-x 1 root root 91296 Jan 14 2022 systemd-sleep
-rwxr-xr-x 1 root root 108048 Jan 14 2022 systemd-socket-proxyd
-rwxr-xr-x 1 root root 66384 Jan 14 2022 systemd-sysctl
lrwxrwxrwx 1 root root 24 Sep 23 2021 systemd-sysv-install -> ../../..//sbin/chkconfig
-rwxr-xr-x 1 root root 384928 Jan 14 2022 systemd-timedated
-rwxr-xr-x 1 root root 416200 Jan 14 2022 systemd-udevd
上面删减了很多。。

 

         Linux内核初始化完成后,init脚本执行程序/sbin/init。

        简单回顾下SysV模式下 ,SysV的 /sbin/init 读取文件/etc/inittab,它决定了要运行的一系列脚本以完成初始化过程:

  1. init 运行的第一个脚本是 /etc/rc.d/rc.sysinit。该脚本执行多项任务
  2. init 所做的下一件事是运行 /etc/rc.d/rc(N).d,并向其传递一个称为运行级别的数字。某些运行级别是标准的:

    0 = 暂停
    1 = 单用户模式
    ​​6 = 重启

    //看下我系统里面的目录
    [root@aozhejin2 /]$ls /etc/rc.d/ init.d rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rc.local

     

    运行级别 2-5 用于各种形式的多用户模式;这些运行级别的确切含义因发行版而异。

    初始运行级别在 /etc/inittab 中指定。

     

       下面看下本机注意: 当您使用systemd时候就不再使用inittab 即 /etc/initab 来init 初始化,而转交给了systemd管理系统

[root@aozhejin2 /usr/local/src/stracetest]$cat /etc/inittab
# 当使用systemd时候,inittab不再使用. (英文原文就是明确备注的 ) # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM. # Ctrl
-Alt-Delete 快捷键由 /usr/lib/systemd/system/ctrl-alt-del.target 这个来处理 # systemd 使用 'targets' 代替 runlevels. 默认的情况下有两个 main targets: # 1.multi-user.target: 类似于runlevel 3 # 2.graphical.target: 类似于runlevel 5 # 浏览默认的请运行,下面的命令: # systemctl get-default # 设置为默认的target,请运行下面命令: # systemctl set-default TARGET.target
[root@aozhejin2
/usr/local/src/stracetest]$cat /usr/lib/systemd/system/ctrl-alt-del.target # 这个文件是systemd的一部分分. # systemd is free software; you can redistribute it and/or modify it [Unit] Description=Reboot Documentation=man:systemd.special(7) DefaultDependencies=no Requires=systemd-reboot.service After=systemd-reboot.service AllowIsolate=yes JobTimeoutSec=30min JobTimeoutAction=reboot-force [Install] Alias=ctrl-alt-del.target

  运行systemctl get-default

[root@aozhejin2 /usr/lib/systemd/system]$systemctl get-default
multi-user.target

    运行  systemctl set-default graphical.target  (target位于/usr/lib/systemd/system/下) 重新设置

  

八、启动agtty
     1. 通过  getty@.service  启动

[root@aozhejin2 /usr/lib/systemd/system]$cat getty@.service
#  This file is part of systemd.
# version 2.1 of the License, or (at your option) any later version.
[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html  
After=systemd-user-sessions.service plymouth-quit-wait.service getty-pre.target
After=rc-local.service

#如果在引导过程中产生了额外的getty,那么我们应该确保在getty.target之前同步,即使getty.target实际上并没有将其引入。
Before=getty.target
IgnoreOnIsolate=yes
# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by serial-getty@.service, not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM    #这里%I即tty1默认
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes
# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
[Install]
WantedBy=getty.target
DefaultInstance=tty1

   实际情况怎么样呢?我们看下

[root@aozhejin2 /usr/lib/systemd/system]$ps -ef | grep agetty
root 870 1 0 2022 tty1 00:00:00 /sbin/agetty --noclear tty1 linux
root 11148 1 0 Mar29 tty6 00:00:00 /sbin/agetty --noclear tty6 linux

  看下agetty打开了什么文件

[root@aozhejin2 /usr/lib/systemd/system]$lsof -p 870
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
agetty  870 root  cwd    DIR  253,0     4096       128 /
agetty  870 root  rtd    DIR  253,0     4096       128 /
agetty  870 root  txt    REG  253,0    49640 268729668 /usr/sbin/agetty
agetty  870 root  DEL    REG  253,0          268633371 /usr/lib/locale/locale-archive  #多语言支持
agetty  870 root  DEL    REG  253,0          268729900 /usr/lib64/libnss_files-2.17.so;64071407
agetty  870 root  DEL    REG  253,0          268633379 /usr/lib64/libc-2.17.so;64071407  //glibc库
agetty  870 root  DEL    REG  253,0          268633367 /usr/lib64/ld-2.17.so;64071407
agetty  870 root    0u   CHR    4,1      0t0      1043 /dev/tty1   #标准输入
agetty  870 root    1u   CHR    4,1      0t0      1043 /dev/tty1   #标准输出
agetty  870 root    2u   CHR    4,1      0t0      1043 /dev/tty1   #标准错误

[root@aozhejin2 /usr/lib/systemd/system]$file /usr/lib/locale/locale-archive
/usr/lib/locale/locale-archive: PDP-11 separate I&D executable not stripped

请参看: https://man7.org/linux/man-pages/man1/localedef.1.html
https://manpages.courier-mta.org/htmlman7/locale.7.html

查看由systemd管理的 getty@tty1.service 服务启动的agetty,我们看到pid=870 是启动的agetty实例

[root@aozhejin2 /usr/lib/systemd/system]$ systemctl status getty@tty1.service
● getty@tty1.service - Getty on tty1
   Loaded: loaded (/usr/lib/systemd/system/getty@.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2022-04-21 08:57:47 CST; 11 months 7 days ago
     Docs: man:agetty(8)
           man:systemd-getty-generator(8)
           http://0pointer.de/blog/projects/serial-console.html
 Main PID: 870 (agetty)
   CGroup: /system.slice/system-getty.slice/getty@tty1.service
           └─870 /sbin/agetty --noclear tty1 linux  启动命令

Warning: Journal has been rotated since unit was started. Log output is incomplete or unavailable.

  因为有两个tty,所以查看另一个

[root@aozhejin2 /usr/lib/systemd/system]$ systemctl status getty@tty6.service
● getty@tty6.service - Getty on tty6
   Loaded: loaded (/usr/lib/systemd/system/getty@.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2023-03-29 18:10:31 CST; 13h ago
     Docs: man:agetty(8)
           man:systemd-getty-generator(8)
           http://0pointer.de/blog/projects/serial-console.html
 Main PID: 11148 (agetty)
   CGroup: /system.slice/system-getty.slice/getty@tty6.service
           └─11148 /sbin/agetty --noclear tty6 linux

Mar 29 18:10:31 aozhejin2 systemd[1]: Started Getty on tty6.

   但是这个tty6自动产生的,这个设备你删除不了,一删除它自动又重新生成,不信你测试一下,它是专门为agetty保留的,这样做是为了确保始终有办法获得文本登录。 
   
 2. 我们可以修改agetty启动参数,从而更有效的控制agetty的行为

修改getty@.service文件, 例如修改ExeStart这行: 
        ExecStart=-/sbin/agetty -o '-p -- \\u' --noissue --noclear %I $TERM 
        #--noissue参数表示不显示 /etc/issue文件内容
        #--noclear表示提示前不要清除屏幕
    重新启动  systemctl restart getty@tty1

 

九、/etc/nsswitch.conf 
    这里需要介绍一下这个问题,它是系统来说是一个很重要的文件,也可以认为是数据库。
   我们利用strace命令继续在细致看下它的打开调用情况

[root@aozhejin2 ~]$strace -e open lsof -p 870
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/proc/filesystems", O_RDONLY)     = 3
open("/dev/null", O_RDWR)               = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
open("/", O_RDONLY)                     = 3
open("/proc/67162/fdinfo/3", O_RDONLY)  = 4
open("/proc/mounts", O_RDONLY)          = 3
open("/proc/locks", O_RDONLY)           = 3
....
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 4
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 4
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 4
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 4
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
open("/usr/lib64/gconv/gconv-modules.cache", O_RDONLY) = 4
agetty  870 root  cwd    DIR  253,0     4096       128 /
agetty  870 root  rtd    DIR  253,0     4096       128 /
agetty  870 root  txt    REG  253,0    49640 268729668 /usr/sbin/agetty
agetty  870 root  DEL    REG  253,0          268633371 /usr/lib/locale/locale-archive
agetty  870 root  DEL    REG  253,0          268729900 /usr/lib64/libnss_files-2.17.so;64071407
agetty  870 root  DEL    REG  253,0          268633379 /usr/lib64/libc-2.17.so;64071407
agetty  870 root  DEL    REG  253,0          268633367 /usr/lib64/ld-2.17.so;64071407
agetty  870 root    0u   CHR    4,1      0t0      1043 /dev/tty1
agetty  870 root    1u   CHR    4,1      0t0      1043 /dev/tty1
agetty  870 root    2u   CHR    4,1      0t0      1043 /dev/tty1
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=67163, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

我们看到这个文件/etc/nsswitch.conf,它配置系统如何使用各种数据库和名称解析机制,什么意思呢?
    我们参看  
https://illumos.org/man/5/nsswitch.conf   我的系统里面 sss 它是由  

本系统是由下面的.so共享库实现

 [root@aozhejin2 ~]$ls /usr/lib64/libnss_sss.so.2

 

    /usr/lib64/libnss_sss.so.2

  下面就是这个文件的做过处理的 /etc/nsswitch.conf

[root@aozhejin2 ~]$cat /etc/nsswitch.conf
# /etc/nsswitch.conf
#这个文件应该在开始时使用最常用的服务进行排序。
# The entry '[NOTFOUND=return]' means that the search for an # entry should stop if the search in the previous entry turned # up nothing. Note that if the search failed due to some other reason # (like no NIS server responding) then the search continues with the # next entry. # 有效的入口包括下面,他们都由不同的共享库实现 # nisplus Use NIS+ (NIS version 3) # nis Use NIS (NIS version 2), also called YP # dns Use DNS (Domain Name Service) # files Use the local files # db Use the local database (.db) files # compat Use NIS on compat mode # hesiod Use Hesiod for user lookups # [NOTFOUND=return] Stop searching if not found so far # To use db, put the "db" in front of "files" for entries you want to be looked up first in the databases # 例如: #passwd: db files nisplus nis #shadow: db files nisplus nis #group: db files nisplus nis passwd: files sss #对应/etc/passwd shadow: files sss #对应/etc/shadow group: files sss #initgroups: files
#表示系统首先尝试通过查询files(即 /etc/hosts)来解析主机名和IP地址,如果失败,接下来通过查询 DNS 服务器,最后通过查询 NIS+ hosts: files dns myhostname
bootparams: nisplus [NOTFOUND=return] files ethers: files netmasks: files #由ifconfig使用 networks: files protocols: files rpc: files services: files sss netgroup: files sss publickey: nisplus automount: files aliases: files nisplus
本文件比较复杂,既有对应内部的库调用,也有对应文件使用等。

   为了更说明问题,我们做个实验,linux中获取用户属性都是通过getpwnam来取得
   首先看下 /bin/login二进制程序的源文件login.c中获取用户属性信息

static void log_audit(struct login_context *cxt, int status)
{
    int audit_fd;
    struct passwd *pwd = cxt->pwd;

    audit_fd = audit_open();
    if (audit_fd == -1)
        return;
    if (!pwd && cxt->username)
        pwd = getpwnam(cxt->username);  

    audit_log_acct_message(audit_fd,
                   AUDIT_USER_LOGIN,
                   NULL,
                   "login",
                   cxt->username ? cxt->username : "(unknown)",
                   pwd ? pwd->pw_uid : (unsigned int)-1,
                   cxt->hostname,
                   NULL,
                   cxt->tty_name,
                   status);

    close(audit_fd);
}
...
//当然login.c 还用到了pam模式

下面我们自己做下实验来看下

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
int main()
{
        struct passwd *p;
        if((p = getpwnam("root")) != NULL)  
        {
          printf("%s:",p->pw_name);
          printf("%s:\n",p->pw_passwd);
          printf("%u:\n",p->pw_uid);
          printf("%u:\n",p->pw_gid);
          printf("%s:\n",p->pw_gecos);
          printf("%s:\n",p->pw_dir);
          printf("%s\n",p->pw_shell);
       }
}
编译
[root@ht8 c]# gcc getpwnam.c //没有指定名称,则自动产生a.out
[root@ht8 c]# ./a.out 
root:x:
0:
0:
root:
/root:
/bin/bash
//我们看看她打开的文件
[root@ht8 c]# strace -e open ./a.out 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
//解析,这个文件很多命令都会用它
open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3   #共享库缓存
//调用libnss库(它会去调glibc库,glibc的libc.so.6中定义了getpwnam)
open("/lib64/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3
//解析
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
root:x:
0:
0:
root:
/root:
/bin/bash
+++ exited with 10 +++
继续解释:
/etc/nsswitch.conf中的passwd是由getpwnam函数解析出来,

   共享库缓存 /etc/ld.so.cache 由ldconfig命令来管理,为了减少共享库系统的库搜索时间,该命令用来刷新系统的共享库缓存 /etc/ld.so.cache 文件。 在安装新的共享库之后,一定要运行 ldconfig 刷新该缓存。
   我们看下getpwnam定义在哪里

//这个函数并不再这里
[root@ht8 c]# objdump -tT /lib64/libnss_files.so.2 | grep getpwnam
0000000000005f00 g     F .text    000000000000013b              _nss_files_getpwnam_r
0000000000005f00 g    DF .text    000000000000013b  GLIBC_PRIVATE _nss_files_getpwnam_r
//有三种方式可以寻找.so链接库内的函数列表
//nm -D  /lib64/libnss_files.so.2
//objdump -tT /lib64/libnss_files.so.2

//继续找 /lib64/libnss_files.so.2 的依赖库
[root@ht8 c]# ldd /lib64/libnss_files.so.2
    linux-vdso.so.1 =>  (0x00007fff07fee000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f6b205a0000)  //
    /lib64/ld-linux-x86-64.so.2 (0x00007f6b20b81000)

//找到getpwnam,注意libc.so.6是C运行时库 glibc的软链接
[root@ht8 c]# nm -D /lib64/libc.so.6 | grep getpwnam
00000000000c42b0 T getpwnam
00000000000c48b0 T getpwnam_r

[root@ht8 c]# readlink /lib64/libc.so.6
libc-2.17.so
[root@ht8 c]# file /lib64/libc.so.6
/lib64/libc.so.6: symbolic link to `libc-2.17.so'
//libc-2.17.so说明
2.1x表示其对应版本,去兼容相应CentOS版本

   /lib64/libnss_files.so.2 会读取 /etc/passwd, /etc/group, /etc/hosts等文件,下面会具体给出哪些库实现了哪些source(nsswitch.conf中的定义叫source) 。     

  我们回过头来看下/etc/nsswitch.conf 里面的各个source由哪些共享库来实现的。
      我们通过 ldconfig -p | grep 
nss_*  来在缓存 /etc/ld.so.cache中进行查找,注意ld.so.cache不能用cat 加管道的方式来匹配

本机64位,centos
共享库位置和名称 source
/usr/lib64/libnss_sss.so.2 实现 sss
/usr/lib64/libnss_files-2.17.so 实现 files
/lib64/libnss_dns.so.2 实现dns
/lib64/libnss_nis.so.2 实现nis
/lib64/libnss_nisplus.so.2 实现nisplus
本库本机没有安装 实现ldap

      这个部分放在这里实在是有点大,可以单独一篇博文,不过为了说明问题,和上面保持一个整体就先放这里。

 

 十、systemd的登录配置文件
      /etc/systemd/logind.conf

   /etc/systemd/logind.conf.d/*.conf

   /run/systemd/logind.conf.d/*.conf

   /usr/lib/systemd/logind.conf.d/*.conf

     get@.service的模板来自 autovt@.service 
  login.
NAutoVTs 取一个正整数。配置默认分配多少个虚拟终端 (VT),当切换到这些虚拟终端且之前未使用时,“ autovt”服务会自动生成。这些服务是从相应 VT TTY 名称的模板单元实例化的 autovt@.service,例如,autovt@tty4.service默认情况下,autovt@.service链接到 getty@.service换句话说,登录提示是在用户切换到未使用的虚拟终端时动态启动的。因此,此参数控制多少登录“gettys" 在 VT 上可用。如果某个 VT 已被某些其他子系统使用(例如,图形登录),则不会尝试这种激活。请注意,配置的 VT 始终受这种激活的影响 ReserveVT=,即使它不是使用该指令配置的 VT 之一NAutoVTs=。默认为 6。设置为 0 时,autovt将禁用“”服务的自动生成。

[root@aozhejin2 /usr/lib/systemd/system]$cat /etc/systemd/logind.conf
#  This file is part of systemd.
# Entries in this file show the compile time defaults.
# You can change settings by editing this file.
# Defaults can be restored by simply deleting this file.
# See logind.conf(5) for details.
[Login]
NAutoVTs=3
#ReserveVT=6
#KillUserProcesses=no
#KillOnlyUsers=
#KillExcludeUsers=root
.....

 查看下systemd-logind状态信息

[root@aozhejin2 ~]$systemctl status systemd-logind
● systemd-logind.service - Login Service
   Loaded: loaded (/usr/lib/systemd/system/systemd-logind.service; static; vendor preset: disabled)
   Active: active (running) since Wed 2023-03-29 17:45:37 CST; 22h ago
     Docs: man:systemd-logind.service(8)
           man:logind.conf(5)
           http://www.freedesktop.org/wiki/Software/systemd/logind
           http://www.freedesktop.org/wiki/Software/systemd/multiseat
 Main PID: 9448 (systemd-logind)
   Status: "Processing requests..."
    Tasks: 1
   Memory: 3.4M
   CGroup: /system.slice/systemd-logind.service
           └─9448 /usr/lib/systemd/systemd-logind

Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 57949 of user root.
Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 1 of user root.
Mar 29 17:45:37 aozhejin2 systemd-logind[9448]: New session 1057 of user root.
Mar 29 18:08:07 aozhejin2 systemd-logind[9448]: Removed session 57949.
Mar 29 18:08:15 aozhejin2 systemd-logind[9448]: New session 57961 of user root.
Mar 29 18:11:39 aozhejin2 systemd-logind[9448]: New session 57963 of user root.
Mar 29 19:55:45 aozhejin2 systemd-logind[9448]: Removed session 57963.
Mar 29 19:55:57 aozhejin2 systemd-logind[9448]: New session 57975 of user root.
Mar 29 20:21:00 aozhejin2 systemd-logind[9448]: Removed session 57975.
Mar 29 20:21:10 aozhejin2 systemd-logind[9448]: New session 57980 of user root.
[root@aozhejin2 ~]$lsof -p 9448
COMMAND    PID USER   FD      TYPE             DEVICE SIZE/OFF      NODE NAME
systemd-l 9448 root  cwd       DIR              253,0     4096       128 /
systemd-l 9448 root  rtd       DIR              253,0     4096       128 /
systemd-l 9448 root  txt       REG              253,0   639832 402655657 /usr/lib/systemd/systemd-logind
systemd-l 9448 root  mem       REG              253,0    61560 269462479 /usr/lib64/libnss_files-2.17.so
systemd-l 9448 root  mem       REG              253,0    19896 268991954 /usr/lib64/libattr.so.1.1.0
systemd-l 9448 root  mem       REG              253,0    19248 268820392 /usr/lib64/libdl-2.17.so
systemd-l 9448 root  mem       REG              253,0   402384 268730267 /usr/lib64/libpcre.so.1.2.0
systemd-l 9448 root  mem       REG              253,0  2156592 268633378 /usr/lib64/libc-2.17.so
systemd-l 9448 root  mem       REG              253,0   142144 269462486 /usr/lib64/libpthread-2.17.so
systemd-l 9448 root  mem       REG              253,0    88720 268633409 /usr/lib64/libgcc_s-4.8.5-20150702.so.1
systemd-l 9448 root  mem       REG              253,0    37064 268991961 /usr/lib64/libacl.so.1.1.0
systemd-l 9448 root  mem       REG              253,0    20048 268991956 /usr/lib64/libcap.so.2.22
systemd-l 9448 root  mem       REG              253,0    43712 269462491 /usr/lib64/librt-2.17.so
systemd-l 9448 root  mem       REG              253,0   155744 268633517 /usr/lib64/libselinux.so.1
systemd-l 9448 root  mem       REG              253,0   163312 281915295 /usr/lib64/ld-2.17.so
systemd-l 9448 root    0r      CHR                1,3      0t0      1028 /dev/null
systemd-l 9448 root    1u     unix 0xffff8a6de94f5500      0t0 640028488 socket
systemd-l 9448 root    2u     unix 0xffff8a6de94f5500      0t0 640028488 socket
systemd-l 9448 root    3u     unix 0xffff8a69cc137700      0t0 640029131 socket
systemd-l 9448 root    4u  a_inode               0,10        0      8534 [eventpoll]
systemd-l 9448 root    5u  a_inode               0,10        0      8534 [timerfd]
systemd-l 9448 root    6r      REG               0,18     4096     28661 /sys/devices/virtual/tty/tty0/active
systemd-l 9448 root    7u  a_inode               0,10        0      8534 [signalfd]
systemd-l 9448 root    8u  netlink                         0t0 640029133 KOBJECT_UEVENT
systemd-l 9448 root    9u  netlink                         0t0 640029134 KOBJECT_UEVENT
systemd-l 9448 root   10u  netlink                         0t0 640029135 KOBJECT_UEVENT
systemd-l 9448 root   11u  netlink                         0t0 640029136 KOBJECT_UEVENT
systemd-l 9448 root   12u     unix 0xffff8a69cc135500      0t0 640029137 socket
systemd-l 9448 root   13u  a_inode               0,10        0      8534 [timerfd]
systemd-l 9448 root   14u      CHR              13,64      0t0      1149 /dev/input/event0
systemd-l 9448 root   15r     FIFO               0,20      0t0 640056595 /run/systemd/sessions/57961.ref
systemd-l 9448 root   16u      CHR                4,6      0t0      1048 /dev/tty6
systemd-l 9448 root   17r     FIFO               0,20      0t0 640217015 /run/systemd/sessions/57980.ref
systemd-l 9448 root   18r     FIFO               0,20      0t0 641501820 /run/systemd/inhibit/1.ref

十一个、添加一个新的tty(前提是该tty设备已存在)

  1)添加新的 agetty:

   在 /etc/systemd/system/getty.target.wants/ 添加新的软链接即可:

[root@aozhejin2 ~]$ln -sf /usr/lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty9.service

   # systemctl start getty@tty9.service

  2)移除 agetty:

 从 /etc/systemd/system/getty.target.wants/ 删除多个对应的软链接即可:

 # rm /etc/systemd/system/getty.target.wants/getty@tty9.service 

 # systemctl stop getty@tty9.service

[root@aozhejin2 /etc/systemd/system]$ps -ef | grep agetty
root        870      1  0  2022 tty1     00:00:00 /sbin/agetty --noclear tty1 linux
root      11148      1  0 Mar29 tty6     00:00:00 /sbin/agetty --noclear tty6 linux
root     105876      1  0 19:00 tty9     00:00:00 /sbin/agetty --noclear tty9 linux

查看下打开的文件

[root@aozhejin.node ~]$lsof -p 105876
COMMAND    PID USER   FD   TYPE DEVICE  SIZE/OFF      NODE NAME
agetty  105876 root  cwd    DIR  253,0      4096       128 /
agetty  105876 root  rtd    DIR  253,0      4096       128 /
agetty  105876 root  txt    REG  253,0     49640 268729668 /usr/sbin/agetty
agetty  105876 root  mem    REG  253,0 106176928 268633366 /usr/lib/locale/locale-archive
agetty  105876 root  mem    REG  253,0     61560 269462479 /usr/lib64/libnss_files-2.17.so
agetty  105876 root  mem    REG  253,0   2156592 268633378 /usr/lib64/libc-2.17.so
agetty  105876 root  mem    REG  253,0    163312 281915295 /usr/lib64/ld-2.17.so
agetty  105876 root    0u   CHR    4,9       0t0      1051 /dev/tty9
agetty  105876 root    1u   CHR    4,9       0t0      1051 /dev/tty9
agetty  105876 root    2u   CHR    4,9       0t0      1051 /dev/tty9

 把当前的tty设置为tty9

[root@aozhejin2 ~]$chvt 9
[root@aozhejin2 ~]$cat /sys/devices/virtual/tty/tty0/active
tty9

 

 

参考资料:
https://man7.org/linux/man-pages/man8/agetty.8.html
https://www.oreilly.com/library/view/linux-in-a/0596000251/re01.html
https://www.physics.udel.edu/~bnikolic/teaching/phys660/RUTE/rute/node35.html
https://www.real-world-systems.com/docs/agetty.1.html  agetty使用说明
https://linux.die.net/man/8/telinit
https://en.wikipedia.org/wiki/Computer_terminal
https://www.physics.udel.edu/~bnikolic/teaching/phys660/RUTE/rute/node35.html  应该意思到这里在说SysVinit
http://glennastory.net/boot/init.html
http://glennastory.net/boot/systemd.html
http://glennastory.net/boot/login.html
http://glennastory.net/boot/getty@.service.txt
http://glennastory.net/boot/ssh.service
http://glennastory.net/boot/startup.html 
https://www.computernetworkingnotes.com/linux-tutorials/differences-between-sysvinit-upstart-and-systemd.html
https://bugzilla.redhat.com/show_bug.cgi?id=1123345
https://mirrors.edge.kernel.org/pub/linux/utils/util-linux/   agtty下载
https://www.man7.org/linux/man-pages/man8/agetty.8.html#ISSUE_FILES    /etc/issue文件讲解
https://grimoire.carcano.ch/blog/linux-console-essential-virtual-terminals-terminal-emulation-locale/  
https://man7.org/linux/man-pages/man2/ioctl_tty.2.html
https://askubuntu.com/questions/902998/how-to-check-which-tty-im-currently-using
https://linux.die.net/man/3/stdout
https://linux.die.net/man/2/
https://linux.die.net/man/2/open
https://subscription.packtpub.com/book/cloud-and-networking/9781801811644/21/ch21lvl1sec85/understanding-logindconf
https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/149.html
https://en.wikipedia.org/wiki/RS-232  串口端口
https://man7.org/linux/man-pages/man8/systemd-getty-generator.8.html
https://www.ibm.com/docs/en/aix/7.1?topic=t-tty-command  tty命令使用
https://codebrowser.dev/glibc/glibc/sysdeps/unix/getlogin.c.html
https://kernel.googlesource.com/pub/scm/utils/util-linux/util-linux/+/master/lib/ttyutils.c
https://github.com/util-linux/util-linux/blob/master/include/ttyutils.h  glibc
https://kernel.googlesource.com/pub/scm/utils/util-linux/util-linux/+/master  util-linux套件源码
https://copyprogramming.com/howto/what-is-the-difference-between-stdin-and-stdin-fileno
http://www.compsci.hunter.cuny.edu/~sweiss/course_materials/unix_lecture_notes/chapter_04.pdf
https://www.thegeekdiary.com/understanding-etclogin-defs-file/
https://www.freedesktop.org/software/systemd/man/systemd.html#
https://forum.salixos.org/viewtopic.php?t=2590  自动登录
https://help.adelielinux.org/html/admin/config.html  与登录有关的配置文件
http://littlesvr.ca/linux-stuff/articles/autologinconsole/autologinconsole.php
https://www.freedesktop.org/software/systemd/man/logind.conf.html
http://0pointer.de/blog/projects/serial-console.html

 http://0pointer.de/blog/projects/serial-console.html 
https://ubuntuforums.org/showthread.php?t=2353287
https://docs.oracle.com/en/operating-systems/oracle-linux/6/admin/about-etc-nsswitch.html
https://www.qnx.com/developers/docs/6.5.0SP1.update/com.qnx.doc.neutrino_utilities/n/nsswitch.conf.html
https://illumos.org/man/5/nsswitch.conf
https://wiki.archlinuxcn.org/zh-hans/Systemd/FAQ
https://docs.oracle.com/cd/E19253-01/816-5174/nsswitch.conf-4/index.html   files列表
https://www.real-world-systems.com/docs/agetty.1.html  设置/etc/issue

 http://0pointer.de/blog/projects/systemd.html  systemd原始设计文档
https://www.oreilly.com/library/view/network-security-hacks/0596006438/ch01s18.html
https://linux.die.net/man/5/login.defs
https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-tty   

posted @ 2023-03-29 09:49  jinzi  阅读(2789)  评论(0编辑  收藏  举报