Ssh

如果我可以在沒有密碼的情況下執行 sudo,為什麼我需要一個 tty 來執行 sudo?

  • January 20, 2021

我已配置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 已經承認了這個問題,它將在未來的版本中刪除。

如果更改伺服器的配置不是一個選項,作為該錯誤配置的解決方法,您可以使用-tor-tt選項ssh在遠端端生成一個偽終端,但要注意它有多個邊效果。

-tt用於互動使用。它將本地終端置於raw模式,以便您與遠端終端互動。這意味著如果sshI/O 不是來自/到終端,那將產生副作用。例如,所有的輸入都會被回顯,特殊的終端字元(^?, ^C, ^U)會引起特殊處理;在輸出時,LFs 將被轉換為CRLFs… (有關更多詳細資訊,請參見為什麼要更改此二進製文件

為了盡量減少影響,您可以將其呼叫為:

ssh -tt host 'stty raw -echo; sudo ...' < <(cat)

< <(cat)將避免在raw模式下設置本地終端(如果有)。而且我們使用stty raw -echo將遠端終端的線路規則設置為通過(實際上它的行為就像將使用的管道而不是沒有 的偽終端-tt,儘管這只適用於該命令執行後,所以你需要延遲發送輸入內容,直到發生這種情況)。

請注意,由於遠端命令的輸出將發送到終端,因此仍會影響其緩衝(對於許多應用程序來說,這將是基於行的)和頻寬效率,因為TCP_NODELAY它已打開。此外-ttssh將 IPQoS 設置lowdelay為相對於throughput。你可以解決這兩種情況:

ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)

另外,請注意,這意味著遠端命令無法在其標準輸入上檢測到文件結尾,並且遠端命令的標準輸出和標準錯誤合併到一個流中。

所以,畢竟不是很好的解決方法。

如果您有辦法在遠端主機上生成一個偽終端(例如使用expect, zsh, socat, perl’s IO::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)。

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