Shell

如何獲取控制終端的真實姓名?

  • March 12, 2019

如何將控制終端的真實名稱(如果有,則錯誤)作為路徑名?

所謂“實名”,我的意思是不是/dev/tty,它不能被其他任意程序用來指代同一個終端。如果可能,我更喜歡將答案作為簡單的 shell 程式碼(如下面的範例),否則作為 C 函式。

請注意,即使標準輸入被重定向,這也必須有效,因此tty無法使用該實用程序:not a tty在這種情況下會出錯,因為tty只列印連接到標準輸入的終端的文件名。

在 Linux 下,可以使用:

echo "/dev/`ps -p $$ -o tty | tail -n 1`"

但這不是可移植的,因為根據 POSIX,終端名稱的格式是 unspecified

關於 C 函式,ctermid (NULL)returns/dev/tty在這裡沒用。

**注意:**根據zsh文件,一個應該能夠做到

zsh -c 'echo $TTY'

但是當標準輸入和標準輸出都被重定向時,目前(版本 5.0.7)失敗:

$ zsh -c 'echo $TTY > /dev/tty' < /dev/null
/dev/pts/9
$ zsh -c 'echo $TTY > /dev/tty' < /dev/null > /dev/null
/dev/tty

“控制終端”又名。ctty,區別於“程序與之互動的終端”。

獲取 ctty 路徑的標準方法是 ctermid(3)。呼叫此命令後, 在 freebsd 10 版之後,會查找實際路徑

$$ 1 $$,而較舊的 freebsd 和glibc 實現$$ 2 $$無條件返回“/dev/tty”]。 ps(1) 來自 linux procps 3.2.8 包,讀取 /proc/*/stat 中的數字條目

$$ 3 $$,然後通過猜測部分扣除路徑名 $$ 4, 5 $$由於缺乏系統支持$$ 6 $$. 但是,如果我們不是對 ctty 感興趣,而是對與 stdio 關聯的任何終端感興趣,則 tty(1) 會列印連接到 stdin 的終端路徑,這與ttyname(fileno(stdin))c 中的相同,另一種選擇是 readlink /proc/self/fd/0.


關於無條件“/dev/tty”行為的不太重要的想法:規範僅說 ctermid 返回的字元串“當用作路徑名時,引用目前控制終端”,而不是一些簡單的“是目前的路徑名控制終端”。它可能被解釋為“/dev/tty”不是控制終端,但如果同一個程序打開(3)它,則僅指控制終端。因此不違反 “一個終端最多可以是一個會話的ctty”規則

$$ 7 $$. 另一個後果是,當我沒有任何控制終端時,ctermid 不會失敗——規範允許這種失敗

$$ 8 $$–,所以只有在隨後的 open(3) 失敗之前,我才能意識到我的 ctty’lessness,這沒關係,因為規範還說在它上面呼叫 open(3) 並不能保證成功。

引用自:https://unix.stackexchange.com/questions/187319