Зачем мне нужен tty для запуска sudo, если я могу sudo без пароля?


226

Я настроил sudoзапуск без пароля, но при попытке ssh 'sudo Foo'все равно получаю сообщение об ошибке sudo: sorry, you must have a tty to run sudo.

Почему это происходит и как я могу обойти это?

Ответы:


290

Это, вероятно, потому что ваш /etc/sudoersфайл (или любой файл, который он включает) имеет:

Defaults requiretty

... что sudoтребует TTY. Известно, что для систем Red Hat (RHEL, Fedora ...) требуется sudoersфайл TTY в файле по умолчанию . Это не дает никакой реальной выгоды для безопасности и может быть безопасно удалено.

Red Hat признала проблему, и она будет устранена в следующих выпусках.

Если изменение конфигурации сервера не является опцией, в качестве обходного пути для этой неправильной конфигурации, вы можете использовать опции -tили -tt, к sshкоторым порождается псевдотерминал на удаленной стороне, но остерегайтесь, что у него есть ряд сторон последствия.

-ttпредназначен для интерактивного использования. Он переводит локальный терминал в rawрежим, позволяющий взаимодействовать с удаленным терминалом. Это означает, что если sshввод / вывод не от / к терминалу, это будет иметь побочные эффекты. Так , например, все входные будет эхом, специальные символы (терминальные ^?, ^C, ^U) будет вызывать специальная обработка; на выходе LFs будет преобразован в CRLFs ... (см. ответ на вопрос « Почему изменяется этот двоичный файл?») .

Чтобы свести к минимуму влияние, вы можете вызвать его как:

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(но не для ввода / вывода), а 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'

(при условии (для обоих), что оболочка входа удаленного пользователя похожа на Bourne).


30

По умолчанию SUDO настроен на использование TTY. То есть SUDO должен запускаться из оболочки входа в систему. Вы можете отменить это требование, добавив -tпереключатель в ваш вызов SSH:

ssh -t someserver sudo somecommand

Распределение -tсил псевдо-тты.

Если вы хотите выполнить это глобально, измените, /etc/sudoersчтобы указать !requiretty. Это может быть сделано для каждого пользователя, группы или всеобъемлющего уровня.


5
Нет, это не по умолчанию. Это только redhat-дистрибутив sudo, который имел requirettyпо умолчанию sudoers. Это будет исправлено в более новых выпусках
Стефан Шазелас

1
@StephaneChazelas +1 за то, что просветил меня, что он в значительной степени является родным для Red Hat и его братьев и сестер, а также для другого ++, если бы я мог, для текущего сообщения об ошибке!
JRFerguson

18

Используйте -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.
Самвин

11

Я столкнулся с этой проблемой, используя 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


1
Этот ответ был наиболее логичным для меня, используя Docker и CentOS 7. Это было легко понять, а также копировать / вставлять!
DaShaun

1

Интересной альтернативой является запуск FreeIPA или IdM для централизованного управления пользователями и правилами sudoer. Затем вы можете создать правила sudo и назначить опцию

! requiretty

в правиле. Команда будет запущена, как ожидается. Вы также будете иметь преимущества управления всеми серверами и пользователями из единого набора конфигураций.


0

Я была такая же проблема. В моем случае решение состояло из двух строк

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

Объяснение:

  • Поместите команды, которые вы хотите запустить (включая команды sudo) в скрипт, например "ssh_test.sh".

  • Прочитайте весь сценарий в переменную с именем «myscript».

  • Вызовите ssh только с одним ключом -t и передайте переменную вместо команды.

До этого я сталкивался с проблемами при использовании комбинаций чтения из стандартного ввода и использования heredocs


-1

Я нашел этот вопрос, в то время как Google, и я столкнулся с этой ошибкой по совершенно другой причине.

Мое исправление состояло в том, чтобы прекратить вызывать сценарии оболочки ниже по потоку, как sudoиз моего родительского сценария оболочки, когда родительский сценарий оболочки уже был вызван с sudo.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.