POSIX规范确实对控制终端所涉及的赌注进行了对冲,因此它定义了:
- 控制终端
- POSIX.1中未解决涉及终端的几个特殊文件中的哪个的问题。路径名
/dev/tty
是与进程关联的控制终端的同义词。
这在“定义”列表中-一切就在那里。但是在“ 通用终端接口”中,还有更多内容:
终端可以作为其控制终端属于进程。具有控制终端的会话的每个进程都具有相同的控制终端。终端可以是最多一个会话的控制终端。会话的控制终端由会话负责人以实现定义的方式分配。如果会话负责人没有控制终端,并且在不使用O_NOCTTY选项的情况下打开了尚未与会话关联的终端设备文件(请参见open()),则实现定义为该终端是否成为会话的控制终端领导。
控制终端在fork()函数调用期间被子进程继承。进程与新的会话创建会话时,将放弃其控制终端setsid()
功能; 保留在旧会话中的其他进程(将其作为控制终端)继续拥有该终端。在与控制终端关联的系统中的最后一个文件描述符关闭时(无论它是否在当前会话中),都不确定是否以该终端作为其控制终端的所有进程都停止拥有任何控制终端。在以这种方式放弃控制终端之后,会话负责人是否以及如何能够重新获取控制终端,这是不确定的。如果其他进程继续将其打开,则进程不会仅通过关闭与控制终端关联的所有文件描述符来放弃其控制终端。
还有很多未指定的地方 -老实说,我认为这是有道理的。尽管终端是关键的用户界面,但在某些情况下它还是各种各样的东西,例如实际的硬件,甚至是打印机,但是在很多情况下,它几乎一无所获-就像xterm
一个模拟器。在那里很难具体说明-而且我认为无论如何都不会对Unix有利,因为终端比Unix做得多。
无论如何,POSIX ps
还很担心ctty的行为。
有-a
开关:
- 编写与终端关联的所有过程的信息。实现可能会从此列表中省略会议负责人。
大。会议负责人可以省略。那不是很有帮助。
和-t
:
- 编写与术语表中给出的与终端相关的过程的信息。应用程序应确保术语列表是单个参数,形式为
<blank>
逗号分隔的列表。终端标识符应以实现定义的格式给出。
...这是另一个令人失望的地方。但这确实是关于XSI系统的说法:
- 在符合XSI的系统上,应以以下两种形式之一给出:设备的文件名(例如
tty04
),或者,如果设备的文件名以开头tty
,则仅在字符后面加上标识符tty
(例如04
)。
那好一点,但不是一条路。同样在XSI系统上,还有-d
开关:
...至少是清楚的。您也可以使用格式字符串指定-o
utput开关tty
,但是,正如您已经注意到的,其输出格式是实现定义的。尽管如此,我认为它仍然是最好的。我认为-通过大量工作,上述开关与其他一些实用程序的结合可以为您提供一个不错的选择。不过,老实说,我不知道它何时/如何为您带来麻烦-而且我也无法想象会发生什么情况。但是,我认为如果我们添加fuser
并且find
可以验证路径的话。
exec 2<>/dev/null
ctty=$(sh -c 'ps -p "$$" -o tty=' <&2)
sid=$(sh -c 'ps -Ao pid= -o tty=|
grep '"$ctty$"' |
grep -Fv "$(ps -do pid=)"' <&2)
find / -type c -name "*${ctty##*/}*" \
-exec fuser -uv {} \; 2>&1 |
grep ".*$ctty.*${sid%%"$ctty"*}"
这些/dev/null
内容只是为了表明当所有搜索子外壳都没有与ctty连接的0,1,2时,它可以工作。无论如何,打印:
/dev/pts/3: mikeserv 3342 F.... (mikeserv)zsh
现在,上面的代码可以在我的机器上获得完整的路径,我想对于大多数人来说,大多数情况下都是如此。我也可以想象它可能会失败。这只是粗略的试探法。
这可能会由于其他许多原因而失败,但是,如果您使用的系统允许会话负责人将所有描述符都放弃给ctty,但仍然保留sid,那么在规范允许的范围内,那么这绝对不会有帮助。就是说,我认为在大多数情况下可以得到很好的估计。
当然,如果将任何描述符连接到您的ctty ,最简单的操作就是...
tty <&2
...或类似。
ps
解决方案涵盖了大多数系统(并who
没有提供更多帮助ps
),可能包含更多的代码来单独处理标识符(例如“ 04”)。我想知道是否有更便携的解决方案。