getty/mingetty 自动登录 16.04

getty/mingetty 自动登录 16.04

我有一个从 14.04 创建的 nfsroot,我正在使用 16.04 重建它。我的 nfsroot 由三个名为 pc1、pc2 和 pc3 的系统共享。还有 3 个匹配的用户帐户,分别名为 pc1、pc2 和 pc3。

当这些系统启动时,它们会自动登录并随后运行 bash 登录脚本。

在 14.04 中,我在 upstart tty1.conf 文件中替换了 mingetty,如下所示:

# tty1 - getty
#
# This service maintains a getty on tty1 from the point the system is
# started until it is shut down again.

start on stopped rc RUNLEVEL=[2345] and (
        not-container or
        container CONTAINER=lxc or
        container CONTAINER=lxc-libvirt)

stop on runlevel [!2345]

respawn
#exec /sbin/getty -8 38400 tty1
script
    exec /sbin/mingetty --autologin `cat /proc/sys/kernel/hostname` --noclear tty1
end script

对我来说,这在 14.04 中运行得很好。它从 /proc 中收集主机名,然后将其用作登录名。

我试图在 16.04 中复制相同的行为,但现在使用 systemd。为此,我修改了 /etc/systemd/system/getty.target.wants。具体来说,我更改了 ExecStart:

ExecStart=-/sbin/agetty -a $HOSTNAME --noclear %I $TERM

但是,通过阅读 systemd 文档和使用一些 google-fu,我了解到在 ExecStart 行中不能使用反引号或环境变量替换。我已测试过对用户帐户进行硬编码,并且它工作正常,但我不知道如何在 systemd 中执行我之前使用 upstart 执行的相同操作。

我也尝试使用一个小脚本来实现此目的,方法是将 ExecStart 行更改为:

ExecStart=/bin/sh -c "/usr/bin/autogetty.sh"

autogetty.sh 脚本是一个简单脚本,用于获取主机名并将其提供给 mingetty。但是它似乎不起作用。我认为问题可能是服务的类型是空闲的,根据我在线的研究,它需要是 fork。我还没有尝试修改服务类型。

我想知道“正确的方法”。到目前为止,我只是在尝试让它发挥作用,即使我让它发挥作用,我也不确定这是否是最好的方法。

谢谢。

答案1

错误观念和错误

我已经了解到我不能在该ExecStart行中使用反引号或环境变量替换。

你学到了一个谎言。事实上,文档并没有这么说。你使用环境变量替换(其语法与大多数 Unix shell 略有不同)。没有HOSTNAME可以替代的环境变量. 设置这样的环境变量后,不会生成服务进程。

单元文件是可参数化的,并且%H参数扩展为(动态)主机名,就像过去从文件加载单元时一样。

ExecStart=/bin/sh -c “/usr/bin/autogetty.sh”
[…]我还没有尝试修改服务类型。

很好。不要。这样做是错误的。只有forking当您的服务实际实现了就绪通知协议时才将其更改为。不要将其作为临时解决方案,因为您错误地创建了一个无缘无故分叉的程序。

因为这正是你所做的。不必要的/bin/sh是分叉一个子进程来运行autogetty.sh,最终会成为运行该 shell 脚本的第二个 shell 进程。然后第二个 shell 进程分叉以mingetty作为孙进程运行。这无论如何都不符合分叉就绪协议,因为它依赖于 fork然后在父级中退出

从 daemontools 的世界吸取教训:服务是运行的,而不是生成的。您运行的程序ExecStart应该服务流程,而不是产卵服务流程。

正确的方式

正确的设置方式如下:

  • 覆盖模板的特定实例,针对特定的终端设备,而不是整个模板。
  • 使用%H获取中的主机名ExecStart。或者使用%m和机器 ID 作为您的用户帐户名。
  • 正确调用事物:
    • 直接运行agetty即可获得最佳效果。实际上,您根本不需要为所述任务编写任何脚本。
    • 如果您仍然选择插入多余的包装脚本:
      • 不要使用/bin/sh -c scriptfile。只需scriptfile使用正确指定的脚本解释器制作可执行文件,然后直接运行它。
      • 确保您的脚本使用execgetty 进程作为守护进程。

进一步阅读

相关内容