Parola olmadan sudo yapabiliyorsam neden sudo çalıştırmak için bir tty'ye ihtiyacım var?


226

sudoParola olmadan çalışacak şekilde yapılandırıldım , ancak denediğimde ssh 'sudo Foo'hata mesajı alıyorum sudo: sorry, you must have a tty to run sudo.

Bu neden oluyor ve bunun üzerinde nasıl çalışabilirim?

Yanıtlar:


290

Bunun nedeni muhtemelen /etc/sudoersdosyanızda (veya içerdiği herhangi bir dosyada):

Defaults requiretty

... ki bu sudobir TTY gerektiriyor. Red Hat sistemlerinin (RHEL, Fedora ...) varsayılan sudoersdosyada TTY gerektirdiği bilinmektedir . Bu hiçbir gerçek güvenlik avantajı sağlamaz ve güvenle kaldırılabilir.

Red Hat sorunu kabul etti ve gelecek sürümlerde ortadan kalkacak.

Sunucunun konfigürasyonunu değiştirmek bir seçenek değilse, bu yanlış konfigürasyon için bir çözüm olarak, uzak taraftaki bir sözde-terminalin ortaya çıktığı -tveya -ttseçeneklerini kullanabilirsiniz ssh; Etkileri.

-ttetkileşimli kullanım içindir. rawUzak terminalle etkileşime girebilmeniz için yerel terminali moda geçirir . Bu, eğer sshG / Ç bir terminalden / uçağa değilse, bunun yan etkileri olacağı anlamına gelir . Örneğin, tüm giriş geri echoed, özel uç karakterleri ( ^?, ^C, ^U) özel işlem neden olur; çıkışta LFs , s'ye dönüştürülecektir CRLF... ( bu cevaba neden bu ikili dosya değiştiriliyor? konusuna bakın).

Etkiyi en aza indirmek için, onu şu şekilde çağırabilirsiniz:

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

< <(cat)Yerel terminalin ayarı (varsa) önleyecektir rawmodu. Ve stty raw -echouzak uçbirimin hat disiplinini geçiş olarak ayarlamak için kullanıyoruz (etkili bir şekilde sözde-uçbirim yerine kullanılacak bir boru gibi davranır -tt, ancak bu komut çalıştırıldıktan sonra da geçerlidir, Bir şey gelinceye kadar giriş için göndermeyi geciktirmek için).

Uzak komutun çıktısı bir terminale gideceğinden, bunun tamponlamayı (birçok uygulama için satır tabanlı olacak) ve açık olduğundan beri bant genişliği verimliliğini etkileyeceğini unutmayın TCP_NODELAY. Ayrıca birlikte -tt, sshhiç IPQoS setleri lowdelayaksine throughput. İkisiyle de çalışabilirsiniz:

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

Ayrıca, uzak komutun, stdinindeki dosyanın sonunu algılayamayacağı ve uzak komutun stdout ve stderr'sinin tek bir akışta birleştirildiği anlamına geldiğine dikkat edin.

Yani, sonuçta etrafta iyi bir iş değil.

Bir uzak ana bilgisayarda sahte terminali sokacak yol var ise (olduğu gibi expect, zsh, socat, perl's IO::Pty...), o zaman sözde-terminali eklemek oluşturmak için bu kullanmak daha iyi olurdu sudo(ama olup I / O), ve kullanıma ssholmadan -t.

Örneğin, şununla 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'

Ya da script(burada uygulamayı varsayarsak 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'

(her ikisi için de) uzaktaki kullanıcının giriş kabuğunun Bourne benzeri olduğunu varsayarak).


30

Varsayılan olarak, SUDO bir TTY gerektirecek şekilde yapılandırılmıştır. Yani, SUDO'nun bir giriş kabuğundan çalıştırılması bekleniyor. -tSSH çağrınıza anahtar ekleyerek bu gereksinimi ortadan kaldırabilirsiniz :

ssh -t someserver sudo somecommand

-tBir psödo-tty'nin kuvvetleri ayırma.

Bunu global olarak yapmak istiyorsanız, /etc/sudoersbelirtmek için değiştirin !requiretty. Bu kullanıcı başına, grup başına ya da her şeyi kapsayan bir seviyede yapılabilir.


5
Hayır, varsayılan değil. requirettyVarsayılan sudo'larında bulunan sudo'nun yalnızca redhat dağılımı . Yeni sürümlerde düzeltilecek
Stéphane Chazelas

1
Mevcut hata raporu için yapabilseydim @StephaneChazelas +1 beni Red Hat, kardeşleri ve bir başka ++ için yerli olduğunu aydınlatıyor!
JRFerguson

18

Tty tahsisini zorlamak için -tbayrağı kullanın ssh.

$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$

-tTahsise zorlamak için ikinci bir saniye ekleyinPseudo-terminal will not be allocated because stdin is not a terminal.
Samveen


1

İlginç bir alternatif, kullanıcılarınızı ve sudoer kurallarınızı merkezi olarak yönetmek için FreeIPA veya IdM çalıştırmaktır. Daha sonra sudo kuralları oluşturabilir ve seçeneği atayabilirsiniz.

! requiretty

Kuralda. Komut daha sonra beklendiği gibi çalışacaktır. Ayrıca, tüm sunucuları ve kullanıcıları tek bir yapılandırma kümesinden yönetme avantajlarına da sahip olacaksınız.


0

Ben de aynı sorunu yaşadım. Benim durumumda çözüm iki satırdı.

myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"

Açıklama:

  • Çalıştırmak istediğiniz komutları (sudo komutları dahil) "ssh_test.sh" gibi bir komut dosyasına yerleştirin.

  • Komut dosyasının tamamını "myscript" adlı bir değişkene okuyun.

  • Ssh komutunu sadece one -t ile çağırın ve değişkeni komut yerine verin.

Bundan önce, stdin'den okuma kombinasyonlarını kullanarak ve heredocs kullanarak problemlerle karşılaştım.


-1

Bu soruyu Googling yaparken buldum ve bu hatayı tamamen farklı bir nedenden dolayı karşıladım.

Düzeltmem, sudoüst kabuk komut dosyası zaten çağrıldığında üst kabuk komut dosyasındaki gibi alt kabuk komut dosyalarını çağırmayı durdurmaktı sudo.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.