Nakonfiguroval jsem sudo
spustit bez hesla, ale když se pokusím ssh 'sudo Foo'
, stále se mi zobrazuje chybová zpráva sudo: sorry, you must have a tty to run sudo
.
Proč se to děje a jak to mohu obejít?
Přijatá odpověď:
Je to pravděpodobně proto, že vaše /etc/sudoers
soubor (nebo jakýkoli soubor, který obsahuje) má:
Defaults requiretty
…což dělá sudo
vyžadovat TTY. Je známo, že systémy Red Hat (RHEL, Fedora…) vyžadují TTY ve výchozím sudoers
soubor. To neposkytuje žádnou skutečnou výhodu zabezpečení a lze jej bezpečně odstranit.
Red Hat tento problém uznal a v budoucích verzích bude odstraněn.
Pokud změna konfigurace serveru nepřichází v úvahu, jako řešení pro tuto chybnou konfiguraci můžete použít -t
nebo -tt
možnosti ssh
který vytváří pseudoterminál na vzdálené straně, ale pozor, má řadu vedlejších účinků.
-tt
je určen pro interaktivní použití. Vloží místní terminál do raw
režimu, abyste mohli komunikovat se vzdáleným terminálem. To znamená, že pokud ssh
I/O není z/do terminálu, což bude mít vedlejší účinky. Například všechny vstupy budou ozvěny zpět, speciální koncové znaky (^?
, ^C
, ^U
) způsobí zvláštní zpracování; na výstupu LF
s budou převedeny na CRLF
s… (viz tato odpověď na Proč se tento binární soubor mění? pro více podrobností.
Chcete-li minimalizovat dopad, můžete jej vyvolat jako:
ssh -tt host 'stty raw -echo; sudo ...' < <(cat)
< <(cat)
zabrání nastavení místního terminálu (pokud existuje) v raw
režimu. A my používáme stty raw -echo
nastavit linkovou disciplínu vzdáleného terminálu jako průchozí (ve skutečnosti se chová jako roura, která by byla použita místo pseudoterminálu bez -tt
, i když to platí až po spuštění tohoto příkazu, takže musíte odložit odeslání něčeho pro vstup, dokud se tak nestane).
Všimněte si, že protože výstup vzdáleného příkazu půjde do terminálu, bude to stále ovlivňovat jeho ukládání do vyrovnávací paměti (které bude pro mnoho aplikací založené na lince) a efektivitu šířky pásma, protože TCP_NODELAY
je zapnuto. Také pomocí -tt
, ssh
nastaví IPQoS na lowdelay
na rozdíl od throughput
. Obojí můžete obejít pomocí:
ssh -o IPQoS=throughput -tt host 'stty raw -echo; sudo cmd | cat' < <(cat)
Všimněte si také, že to znamená, že vzdálený příkaz nemůže detekovat konec souboru na svém stdin a stdout a stderr vzdáleného příkazu jsou sloučeny do jednoho proudu.
Související:Debian – Odebrat uživatele a heslo při přihlášení v Debian 9 Stretch?Takže to nakonec není tak dobré řešení.
Pokud máte způsob, jak vytvořit pseudoterminál na vzdáleném hostiteli (jako u expect
, zsh
, socat
, perl
's IO::Pty
…), pak by bylo lepší použít to k vytvoření pseudoterminálu pro připojení sudo
to (ale ne pro I/O) a použijte ssh
bez -t
.
Například s 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'
Nebo pomocí script
(zde za předpokladu implementace z 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'
(za předpokladu (pro oba), že přihlašovací shell vzdáleného uživatele je podobný Bourneovi).