如何獲取控制終端的真實姓名?
如何將控制終端的真實名稱(如果有,則錯誤)作為路徑名?
所謂“實名”,我的意思是不是
/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) 並不能保證成功。