C 从终点站向上看
专家们, 我有一个通过ssh连接到服务器的客户端(它得到了一个tty分配)。我有一个进程a正在服务器上运行。现在,每当客户机断开连接时,我都需要了解消失的tty 我在想,既然SSHD知道会话正在消亡(在超时或简单退出之后),它就可以生成一个信号来处理会话 有没有其他方法可以让A获得关于tty的信息,这些信息会像在SIGHUP上收听tty一样消失?我正在Linux上用C编写代码C 从终点站向上看,c,linux,process,ssh,signals,C,Linux,Process,Ssh,Signals,专家们, 我有一个通过ssh连接到服务器的客户端(它得到了一个tty分配)。我有一个进程a正在服务器上运行。现在,每当客户机断开连接时,我都需要了解消失的tty 我在想,既然SSHD知道会话正在消亡(在超时或简单退出之后),它就可以生成一个信号来处理会话 有没有其他方法可以让A获得关于tty的信息,这些信息会像在SIGHUP上收听tty一样消失?我正在Linux上用C编写代码 感谢您的帮助。您面临两个问题,都很困难。简洁的回答是“你不能”;较长的答案是“如果不做重大修改,你就不能” 信号传递的信
感谢您的帮助。您面临两个问题,都很困难。简洁的回答是“你不能”;较长的答案是“如果不做重大修改,你就不能”
sau SIGINFO
,您可以找到发送信号的进程的进程ID,但在您的方案中,这将是sshd
,这并没有太大的帮助。因此,很难(几乎不可能)通过信号获得关于哪个终端的信息。显然,可以定义其他方案,但必须将信息写入文件或类似文件sshd
,以记录有关它将哪个终端分配(或被分配)给其子进程的信息,然后安排它在子进程终止时将该信息发送给您的进程A。这充其量也会很棘手sshd
运行你设计的一个特殊过程,这反过来会分叉,孩子运行sshd
否则会运行的过程。父级(a)记录子级连接到哪个终端,并且(b)等待子级终止。当它这样做时,它将终端信息写入进程A将找到它的某个地方,然后退出。您仍然需要修改sshd
,并且您必须设计一种机制,使父进程知道作为子进程运行什么(但这可能不是很难;您保持参数列表不变,只是让sshd
执行您的监视进程,而不是指定为argv[0]的任何进程)
…父级使用argv[0]
作为execvp()
的文件参数
此方案最大限度地减少了对
sshd
的更改(但仍需要非标准版本)。您必须仔细编写父代码,并且必须与进程A配合。所有这些都非常重要。POSIX.1提供了一个工具,其中列出了当前登录的用户、他们的终端和其他信息。在Linux中,这与utmp相同;有关更多信息,请参阅
OpenSSH确实维护utmp记录
下面是一个简单的示例,其中列出了当前从远程计算机登录的所有用户、他们使用的终端以及用户拥有的初始进程组:
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <utmpx.h>
int main(void)
{
struct utmpx *entry;
setutxent();
while ((entry = getutxent()))
if (entry->ut_type == USER_PROCESS && entry->ut_host[0] != '\0')
printf("%s is logged in on /dev/%s from %s and owns process group %d\n",
entry->ut_user, entry->ut_line, entry->ut_host,
(int)getpgid(entry->ut_pid));
return 0;
}
#定义POSIX_C_SOURCE200809L
#包括
#包括
#包括
#包括
内部主(空)
{
结构utmpx*条目;
setutxent();
而((entry=getutxent())
如果(条目->ut\U类型==用户\U进程和条目->ut\U主机[0]!='\0')
printf(“%s从%s登录到/dev/%s并拥有进程组%d\n”,
条目->ut\U用户,条目->ut\U行,条目->ut\U主机,
(int)getpgid(entry->ut_pid));
返回0;
}
在您的情况下,我希望进程A维护一个远程连接用户的列表,并定期执行如上所述的类似循环,以更新已知条目的状态并添加新条目;删除不再可见的条目
然后,新条目与“登录”事件匹配,不再显示的条目与“注销”事件匹配(并在循环后删除),所有其他事件都是“仍然登录”用户
就所用CPU时间和所用I/O而言,上面的循环相当轻量级是二进制格式的,如果经常访问,通常在页面缓存中。条目相对较小,即使在有很多用户的服务器上,文件读取的大小也不超过1兆字节。不过,我不会在一个严格的循环中执行
就我个人而言,我通常会等待
UTMPX\u文件上的WRITE
事件(/var/run/utmp
在大多数Linux机器上),然后在每个事件后重新读取记录。这样,服务将在大部分时间阻塞inotify文件描述符上的read(),并几乎立即对任何登录/注销事件做出反应。谢谢。但是,真正的问题是我不能有一个特殊的过程。当我通过ssh登录时,我启动一个特殊的shell,它处理来自ssh客户端的请求。这个shell使用套接字与a通信以获取一些信息。因此每个ssh客户端都有自己的shell launched和用户选择是否通过客户端外壳获取重定向的标准输出。如果用户选择通过客户端外壳获取标准输出,我需要处理客户端终止。即进程A不应再将标准输出重定向到客户端外壳。这就是我遇到问题的地方,因此出现了上述问题。然后是与将必须安排A知道它何时终止。一种可能是让shell创建并打开FIFO进行写入,而进程A打开FIFO进行读取。进程A可以安排在FIFO的另一端关闭时被告知,然后删除FIFO。这听起来是个好主意。让我试试。但是如果客户端终止abru突然(例如网络问题),这个shell会被删除吗?(记住当用户使用特定的loginid登录时,我在passwd文件中启动这个shell)。如果shell被杀死,除非FIFO被明确关闭,否则FIFO仍然保留,并且A不会得到任何正确的通知?通过。。