ผมได้กำหนดค่าsudo
ให้ทำงานโดยไม่มีรหัสผ่าน แต่เมื่อฉันพยายามผมยังได้รับข้อความแสดงข้อผิดพลาดssh 'sudo Foo'
sudo: sorry, you must have a tty to run 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 ... ) เป็นที่รู้จักกันว่าต้องการ TTY ในsudoers
ไฟล์เริ่มต้น ที่ไม่มีประโยชน์ด้านความปลอดภัยที่แท้จริงและสามารถลบออกได้อย่างปลอดภัย
Red Hat ยอมรับปัญหาแล้วและจะถูกลบออกในอนาคต
หากการเปลี่ยนการกำหนดค่าเซิร์ฟเวอร์ไม่ใช่ตัวเลือกเนื่องจากการแก้ไขปัญหาสำหรับการกำหนดค่าผิดพลาดนั้นคุณสามารถใช้ตัวเลือก-t
หรือ-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)
นอกจากนี้โปรดทราบว่าหมายถึงคำสั่งรีโมตไม่สามารถตรวจพบจุดสิ้นสุดไฟล์บน stdin และ stdout และ stderr ของคำสั่งรีโมตรวมเข้าด้วยกันเป็นสตรีมเดียว
ดังนั้นการทำงานที่ไม่ดีนัก
ถ้าคุณได้มีวิธีการที่จะวางไข่หลอกขั้วในพื้นที่ห่างไกล (เช่นกับ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'
(สมมติว่า (สำหรับทั้งคู่) ว่าเชลล์ล็อกอินของผู้ใช้รีโมตนั้นเป็นแบบบอร์น)
โดยค่าเริ่มต้น SUDO ถูกกำหนดค่าให้ต้องใช้ TTY นั่นคือ SUDO คาดว่าจะเรียกใช้จากเปลือกเข้าสู่ระบบ คุณสามารถเอาชนะข้อกำหนดนี้ได้โดยเพิ่ม-t
สวิตช์ไปยังการเรียกใช้ SSH ของคุณ:
ssh -t someserver sudo somecommand
การ-t
จัดสรรกองกำลังของ pseudo-tty
หากคุณต้องการที่จะดำเนินการนี้ทั่วโลกปรับเปลี่ยนเพื่อระบุ/etc/sudoers
!requiretty
ซึ่งสามารถทำได้ต่อผู้ใช้ต่อกลุ่มหรือระดับที่ครอบคลุมทั้งหมด
ใช้-t
แฟล็กssh
เพื่อบังคับการจัดสรร tty
$ ssh luci tty
not a tty
$ ssh luci -t tty
/dev/ttys003
$
-t
ในการบังคับจัดสรรเมื่อPseudo-terminal will not be allocated because stdin is not a terminal.
ฉันพบปัญหานี้โดยใช้ Docker และ Centos 7 ฉันทำสิ่งต่อไปนี้:
yum install -y sudo
sed -i -e 's/Defaults requiretty.*/ #Defaults requiretty/g' /etc/sudoers
ฉันพบแฮ็คนี้ที่https://hub.docker.com/r/liubin/fluentd-agent/~/dockerfile
ทางเลือกที่น่าสนใจคือการเรียกใช้ FreeIPA หรือ IdM เพื่อจัดการผู้ใช้ของคุณและกฎ sudoer จากส่วนกลาง จากนั้นคุณสามารถสร้างกฎ sudo และกำหนดตัวเลือก
! requiretty
ในกฎ คำสั่งจะทำงานตามที่คาดไว้ คุณจะได้รับประโยชน์จากการจัดการเซิร์ฟเวอร์และผู้ใช้ทั้งหมดจากการกำหนดค่าชุดเดียว
ฉันมีปัญหาเดียวกัน ในกรณีของฉันการแก้ปัญหาคือสองบรรทัด
myscript=$(cat ssh_test.sh)
ssh -t user@host "$myscript"
คำอธิบาย:
วางคำสั่งที่คุณต้องการเรียกใช้ (รวมถึงคำสั่ง sudo) ลงในสคริปต์เช่น "ssh_test.sh"
อ่านสคริปต์ทั้งหมดเป็นตัวแปรที่เรียกว่า "myscript"
เรียกใช้ ssh ด้วยหนึ่ง -t และจัดหาตัวแปรแทนคำสั่ง
ก่อนหน้านี้ฉันพบปัญหาในการใช้ชุดค่าผสมของการอ่านจาก stdin และการใช้ heredocs
ฉันพบคำถามนี้ขณะที่ Google และฉันพบข้อผิดพลาดนี้ด้วยเหตุผลที่แตกต่างอย่างสิ้นเชิง
การแก้ไขของฉันคือการหยุดเรียกเชลล์สคริปต์ปลายน้ำเป็นจากเชลล์สคริปต์พ่อแม่ของฉันเมื่อสคริปต์เชลล์แม่ได้แล้วเรียกว่ามีsudo
sudo
requiretty
อยู่ใน sudoers ที่เป็นค่าเริ่มต้น มันจะได้รับการแก้ไขในรุ่นที่ใหม่กว่า