如果我可以在沒有密碼的情況下執行 sudo,為什麼我需要一個 tty 來執行 sudo?
我已配置
sudo
為無需密碼即可執行,但是當我嘗試執行時ssh 'sudo Foo'
,我仍然收到錯誤消息sudo: sorry, you must have a tty to run sudo
。為什麼會發生這種情況,我該如何解決?
這可能是因為您的
/etc/sudoers
文件(或它包含的任何文件)具有:Defaults requiretty
…這
sudo
需要一個 TTY。眾所周知,Red Hat 系統(RHEL、Fedora…)在預設sudoers
文件中需要 TTY。這並沒有提供真正的安全優勢,並且可以安全地刪除。Red Hat 已經承認了這個問題,它將在未來的版本中刪除。
如果更改伺服器的配置不是一個選項,作為該錯誤配置的解決方法,您可以使用
-t
or-tt
選項ssh
在遠端端生成一個偽終端,但要注意它有多個邊效果。
-tt
用於互動使用。它將本地終端置於raw
模式,以便您與遠端終端互動。這意味著如果ssh
I/O 不是來自/到終端,那將產生副作用。例如,所有的輸入都會被回顯,特殊的終端字元(^?
,^C
,^U
)會引起特殊處理;在輸出時,LF
s 將被轉換為CRLF
s… (有關更多詳細資訊,請參見為什麼要更改此二進製文件?為了盡量減少影響,您可以將其呼叫為:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
這
< <(cat)
將避免在raw
模式下設置本地終端(如果有)。而且我們使用stty raw -echo
將遠端終端的線路規則設置為通過(實際上它的行為就像將使用的管道而不是沒有 的偽終端-tt
,儘管這只適用於該命令執行後,所以你需要延遲發送輸入內容,直到發生這種情況)。請注意,由於遠端命令的輸出將發送到終端,因此仍會影響其緩衝(對於許多應用程序來說,這將是基於行的)和頻寬效率,因為
TCP_NODELAY
它已打開。此外-tt
,ssh
將 IPQoS 設置lowdelay
為相對於throughput
。你可以解決這兩種情況:ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
另外,請注意,這意味著遠端命令無法在其標準輸入上檢測到文件結尾,並且遠端命令的標準輸出和標準錯誤合併到一個流中。
所以,畢竟不是很好的解決方法。
如果您有辦法在遠端主機上生成一個偽終端(例如使用
expect
,zsh
,socat
,perl
’sIO::Pty
…),那麼最好使用它來創建要附加sudo
到的偽終端(但是不適用於 I/O),並且ssh
不使用-t
.例如,使用
expect
:ssh host 'expect -c "spawn -noecho sh -c { exec sudo cmd >&4 2>&5 <&6 4>&- 5>&- 6<&-} exit [lindex [wait] 3]" 4>&1 5>&2 6<&0'
或者使用
script
(這裡假設實現util-linux
):ssh host 'SHELL=/bin/sh script -qec " sudo cmd <&3 >&4 2>&5 3<&- 4>&- 5>&- " /dev/null 3<&0 4>&1 5>&2'
(假設(對於兩者)遠端使用者的登錄 shell 類似於 Bourne)。