如何区分在Linux控制台和SSH会话中运行?

9
我有一个应用程序,如果直接从Linux控制台运行,则需要以不同的方式运行。因此,如果用户使用SSH连接运行FooBar,或者用户走到控制台并直接登录以运行FooBar,则希望它执行不同的操作。
我需要调用哪个C API来区分这两种情况?我想我得查看“tty / pts”信息(例如当我运行“ps axf”时所看到的信息),但我不确定这是否是最佳解决方案,也不知道要调用哪个API来获取该信息。
感谢您的提示。 :)

有其他方法可以获取非tty shell会话,而不是通过SSH连接。例如,我现在正在我的桌面上使用KDE中的Konsole...我在计算机上,但当我运行“who”时,它显示为pty。对于您的目的,这是否算作控制台或“ssh”会话?也许您应该编辑您的问题以更清楚地表达。 - rmeador
我认为你在询问两件不同的事情...实际问题似乎是如何判断你是在本地X终端还是通过ssh会话运行。 "Linux控制台"通常指使用[Ctrl+] Alt + F2等访问的硬件控制台。如果$TERM == "linux",则可以检测到后者。 - Gringo Suave
5个回答

9

根据您对欺骗的担忧程度不同,一种简单的检查方法是查看SSH_CLIENT和SSH_CONNECTION环境变量是否存在或不存在,此时您需要使用getenv函数。


6

检查ttyname(3)的返回值与您的标准输入进行比较,应该可以给出馈送进程输入的终端名称。

如果程序在控制台上运行(并且没有重定向其输入),则它将是/dev/console。您也可以检查stdout是否连接到/dev/console - 看看哪个更适合您的使用情况。


5
这并不是/dev/console,而是/dev/tty[0-9],而ssh和gnome-terminal会显示为/dev/pts/[0-9]+这样的名称。结合使用isatty()和ttyname()函数,非常适合我需要做的事情。 - Stéphane

5

ttyname函数可以告诉你与给定文件描述符相连的终端名称;例如,ttyname(0)将告诉你标准输入的终端。

当然,如果输入或输出被重定向,这将会失败。

除此之外,你可以检查各种环境变量(SSH_CONNECTIONSSH_CLIENTREMOTEHOSTDISPLAYSESSIONNAME)。Wireshark有逻辑来检测它是否在远程运行,以便不捕获它生成的网络流量;你可能会对其get_conn_cfilter函数使用的逻辑感兴趣。


1
Wireshark源代码中发现了不错的问题! - ivans

3

我建议查看环境变量以了解发生了什么。我不确定你需要哪个C API,但肯定有一个。

例如,无论使用哪个SSH客户端,我的机器上都设置了SSH_CLIENTSSH_CONNECTION环境变量。

根据运行在机器上的SSH服务器,检查这些环境变量的普遍性可能是值得的。


1
该死,developmentalinsanity 比我先完成了 ;) 我不应该花那么长时间写... - Darien

0

丑陋但有效:

// don't force scripts to pause!
if (_isatty(_fileno(stdout)))
{
    _tprintf(_T("\nPress enter to continue..."));
    _gettc(stdin);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接