我正在使用以下/etc/inittab
文件(systemv):
# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $
# The default runlevel.
id:5:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
#
# Runlevel 0 is halt.
# Runlevel 1 is single-user.
# Runlevels 2-5 are multi-user.
# Runlevel 6 is reboot.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# Normally not reached, but fallthrough in case of emergency.
z6:6:respawn:/sbin/sulogin
S0:12345:respawn:/sbin/getty -L 115200 ttyS0
为了了解事情的真正运作方式,如果您对 1-3 的回答能够区分两种情况,我将不胜感激:
- 我使用串行端口连接到我的系统。
- 我有一台“常规”台式电脑。
问题:
如果我添加另一条 getty 行,一旦 linux 启动,我将看到两个单独的终端?
如果我打开几行 getty,我如何指定哪个 getty 将运行我的
si::sysinit:/etc/init.d/rcS
命令以及哪个 getty 将运行其他脚本的命令? (根据系统运行级别运行脚本的)换句话说:在
/etc/inittab
文件中 - 我可以将不同的命令分配给不同的 getty 吗? (我的意思是这些 getty 将打开的终端)/etc/init.d/rc5 文件夹中的最后一个脚本运行以下命令:
su nobody -c /bin/sh
输出是:
sh: cannot set terminal process group (1618): Inappropriate ioctl for device sh: no job control in this shell sh-4.3$ whoami nobody
所以我验证了我不是任何人,但为什么它写前两行?还有为什么提示是 sh-4.3$ 而不是 nobody@...
我正在使用串行连接。我可以更改 /etc/inittab 文件和 init 将运行的最后一个脚本吗,以便:
- 在以低特权用户身份登录之前运行程序(init 进程将等待终止)
- 程序退出后,我的系统会收到常规登录提示
- 创建低特权用户并让他在 init 过程中运行该程序的最佳方法是什么(如果我不想使用无人用户)
答案1
问题一:
是的,通过添加更多getty
线路,您可以获得更多并行端子。一次getty
只能与一台终端设备关联,因此getty
每个串行端口只能关联一个。在常规台式 PC 上,Linux 内核定义了许多虚拟控制台,可以使用Control+ Alt+FX组合键访问并与/dev/ttyX
设备相对应(X = 数字)。确切的设置可能因发行版而异,但通常在主流发行版上,系统正常运行时,前 6 个左右的/dev/ttyX
设备已为其配置。getty
您可以使用openvt
和deallocvt
命令来添加或删除虚拟控制台并在其上启动进程(可以是任何进程,不一定是getty
s)。
/dev/tty0
比较特殊:它指的是当前选择的虚拟控制台。/dev/console
是一个类似的特殊设备,指向定义为主要内核级系统控制台的任何 TTY 设备。在桌面系统上,默认情况下它实际上是一个别名/dev/tty0
,但通过使用console=
引导选项,您可以将其切换到串行端口。例如,在某些嵌入式架构上,默认情况下它可能是串行端口。像这样的实用程序xconsole
也可以充当/dev/console
.
当计算机是专用计算机房中的大型多机柜设备时,向 发送消息是/dev/console
联系计算机附近的值班系统操作员的一种方式,这对于更改磁带或磁盘包等请求可能很有用。在现代系统上,专门发送的消息/dev/console
通常是启动/关闭消息,或者可能是针对可能影响网络或存储访问甚至涉及内核崩溃的故障情况发出紧急警报的最后手段:“负责系统的人员物理硬件需要看到这一点,并且通常的日志文件由于某种原因无法使用。”
问题2:
恐怕你在这里有一个误解。该sysinit
生产线和其他生产线与流程根本/etc/inittab
没有关联。除非另有说明,getty
从 执行的每个命令都有与 关联的标准输入、输出和错误流。inittab
/dev/console
这些getty
行实际上指定了他们将使用的 TTY 设备,并且该getty
进程内置了代码,将为自己及其所有子进程分配该 TTY 设备,除非/直到用户运行 shell 并选择以其他方式重定向这些流。初始化 TTY 设备的设置是getty
其目的的最大部分:显示/etc/issue
登录提示、接受用户名、设置 TERM 环境变量并开始 TTY 登录过程的下一步(通常/bin/login
但可自定义)是有效的只是小部分。
请注意,对于 TTY 设备,有一个约定,该行第一列中的两个字符 ID 字段inittab
应与前缀后有问题的 TTY 设备的名称相匹配/dev/tty
,因此/dev/ttyS0
将获得 inittab 行 ID S0
,等等在。对于根本不一定与任何 TTY 关联的内容(或者如果需要,仅将紧急内容输出到 /dev/console),ID 可以是与 TTY 设备线路 ID 不冲突的任何内容。
(在串行连接终端成为常态的日子里,为线路另一端的终端正确设置 TTY 设备,并将该终端重置为已知的登录状态是非常重要的任务,因为有许多相互竞争的终端类型标准。)
inittab
例如,如果您配置一条线路来运行脚本,您可以查看是否/dev/ttyX
存在特定的虚拟控制台设备。如果没有,您可以使用openvt -c X <command>
创建虚拟控制台并在其上启动命令;如果虚拟控制台设备已经存在,您可以简单地启动您想要的任何命令,并将标准输入、输出和错误重定向到它。例如,您可以指定如下 inittab 行:
6:345:respawn:/usr/local/sbin/myscript
然后/usr/local/sbin/myscript
是这样的(免责声明:未经测试,我手头没有带有 SysVinit 的系统,如果您可以改进它,请随意编辑):
#!/bin/sh
if [ -c /dev/tty6 ]; then
exec <some command> </dev/tty6 >/dev/tty6 2>&1
else
exec openvt -c 6 -w <some command>
fi
respawn
该inittab
行确保进程因任何原因终止时将自动重新启动。345
是此进程应运行的 SysVinit 运行级别列表。如果您需要它在所有常规运行级别上运行,请输入12345
。
请注意,只有当 inittab 行放在该sysinit
行之后时,这才按预期工作,因此可以假定 的初始化udev
已完成。如果您想在初始化过程的早期执行此操作,则可能必须首先为已加载驱动程序的设备创建实际的设备节点;一旦udev
运行,它应该在设备驱动程序初始化时自动创建设备节点。
如果使用串行端口,该openvt
命令将不适用。
所以是的,您绝对可以将不同的命令附加到不同的 TTY 设备。如果命令具有像 s 那样的内置功能,这会很有帮助getty
,但您也可以通过脚本来完成。
(如果您设置的内容比简单的设置更复杂,tail -f
以便在未使用的虚拟控制台中永久查看某些日志,则您应该阅读man setsid
并查看它是否适用于您的计划。)
问题3:
为特定非 root 用户初始化 TTY 会话不仅仅是使用su
.
错误消息
sh: cannot set terminal process group (1618): Inappropriate ioctl for device
sh: no job control in this shell
可能是由设备关联的 shell 引起的,/dev/console
而不是由特定的 TTY 设备引起的。由于/dev/console
它只是当前系统控制台的别名,因此它不具有可用的全套 TTY 控制 ioctl 功能。
如果没有登录脚本为PS1
环境变量分配更有用的值,则默认提示/bin/sh
可以是简单的sh-<version>$
。
问题4:
是的你可以。您应该将“最后一个脚本”指定为wait
-type 行inittab
,并将其放置在前getty
与您的串行线对应的线。
如果不了解有关您的环境的更多详细信息,就很难说哪一个是最好的为此目的创建低权限用户的方法。
答案2
是的,假设线路被赋予唯一标识符并且配置的终端线路可用:
S1:12345:respawn:/sbin/getty -L 115200 ttyS1
将在连接到的串行端口上打开一个终端
ttyS1
。中的行
inittab
不连续,也不与登录相关。每一行描述了在给定的一组运行级别中要采取的操作。因此si::sysinit:/etc/init.d/rcS
指定应在处理系统初始化时init
运行;/etc/init.d/rcS
这发生在可以登录之前。 (看联机inittab(5)
帮助页了解详情)。要将不同的命令分配给
getty
特定终端上的不同 s,您可以配置getty
调用本身,例如通过更改login
它启动的程序(-l
大多数getty
实现中的选项):S0:12345:respawn:/sbin/getty -L 115200 -l /bin/my-t0-login ttyS0 S1:12345:respawn:/sbin/getty -L 115200 -l /bin/my-t1-login ttyS1
/etc/init.d/rc 5
在可以登录之前运行,并且它运行的程序没有连接到终端(“正确”,这就是它的作用getty
- 它为您打开终端并将其启动的程序连接到终端),因此当su nobody -c /bin/sh
调用时, shell 找不到它期望的终端设置,因此禁用作业控制。该sh-4.3$
提示符是 Bash 4.3 作为 运行时的默认提示符/bin/sh
。如果您的程序仅在用户开始登录后运行,那么您可以将其挂接到
getty
;使用的登录序列中。但这样的程序将以 root 身份运行。根据您的具体需求,您可能最好使用 initscript 而不是/etc/inittab
自定义脚本或sudo
shell 的启动脚本。
答案3
刚才第二个(长!)答案已经发布。我必须说第一个解释得很好。目前我想评论第三点:这不是时间问题,而是控制“真实虚拟”tty 的进程的问题,而不仅仅是“控制台虚拟”的问题。
在您可以“使用作业控制”启动 shell 之前,您必须设置即打开 ttyN。 “通用”命令是getty
。从此tty-你得到的东西可以启动一个shell,而不仅仅是后那。
这就像尝试首先启动窗口管理器,然后启动 xorg,而不是与 xinit 一起“启动”它们。我认为。 “会议领导者”。
因为
xx:12:...:program
并且,相反:
aa:1:...:pr_1
bb:1:...:pr_2
...你会得到一个 N:M 关系(如果你滥用的话,你也会变得一团糟——许多 RL,每个 RL 都有许多不同的 progs)。你可以走得更远,但自从不同种类的 RC“标准”开始流行以来。 “Runcom”。有了它们,inittab 看起来很简单,但所有的复杂性都在这些脚本中。
但你的 inittab 看起来简单且正确 - 只有最后一条注释和“z6”条目......
也许你的“su nobody”只需要在之前/周围有一个“getty ... ttyN”。su
而不是login
,并且没有重生。至少应该给出除“不适当”之外的另一个错误消息。
结论(阅读第二个答案后):您不需要复杂的init.d
系统,原始 inittab 足够灵活。只需要正确理解概念和细节即可。
您可以设置三种运行级别:一种使用 ttyN,一种使用 ttySN,一种启动两者的 RL。它是一个可以使用引导加载程序添加的引导参数。在您的情况下,运行级别“5”只是默认值。您选择一个内核、一个 root= 和一个要初始化的运行级别。
“重生”操作是 sysvinit 过去/现在实际需要的。它没有做的事情还有很多,在脚本中实现的可能性也更少。但是,如果您退出(或崩溃)“最后”外壳层,则需要一个安全网。
sysvinit 甚至可以通过错误“生成太快——忽略 5 分钟...”来检测错误配置。