4

робот:

#!/bin/bash
sudo echo apple
sudo cat << EOF
banana
EOF

командная строка:

$ sudo true
[sudo] password for vb:
$ ./robot
apple
banana
$ ./robot > /dev/null
$ ./robot &> /dev/null
[sudo] password for vb:

Почему sudo(1) запрашивает пароль, когда перенаправляются stdout и stderr?

2 ответа2

3

Sudo запоминает ваш пароль (вашу аутентификацию) в течение некоторого времени, поэтому вам не нужно вводить пароль для нескольких команд подряд.

Продолжительность контролируется оператором timestamp_timeout в /etc/sudoers . Читайте man sudoers для получения дополнительной информации.

Более интересным является вопрос о том, как запоминается ваша аутентификация. Каждый раз, когда вы используете sudo, sudo будет создавать файл в каталоге /var/run/sudo/username (Ubuntu 10.04). Имя файла берется из вашего текущего терминала (или tty). Это означает, что sudo запоминает вашу аутентификацию для каждого терминала. Если вы переключитесь на другой терминал, sudo не будет помнить, что вы просто использовали sudo на предыдущем терминале.

Демонстрация:

Используйте sudo:

$ sudo echo foo
[sudo] password for lesmana: 
foo

Смотрите файл, созданный в /var/run/sudo/username:

$ sudo ls -l /var/run/sudo/lesmana
total 0
-rw------- 1 root lesmana  0 2011-04-25 16:56 1

Обратите внимание, что это sudo не спрашивает пароль. Файл назван 1 потому что я запустил команду sudo с номера tty (или pts) 1. Используйте команду tty чтобы увидеть ваше имя tty.

$ tty
/dev/pts/1

Теперь переключитесь на другой терминал:

$ tty
/dev/pts/2

Используйте sudo в этом терминале.

$ sudo echo bar
[sudo] password for lesmana: 
bar

Обратите внимание, что он запрашивает пароль.

Смотрите файл, созданный в /var/run/sudo/username:

$ sudo ls -l /var/run/sudo/lesmana
total 0
-rw------- 1 root lesmana 0 2011-04-25 16:56 1
-rw------- 1 root lesmana 0 2011-04-25 16:57 2 # <-- new

Теперь переключитесь на виртуальную консоль.

$ tty
/dev/tty/1

Используйте sudo:

$ sudo echo baz
[sudo] password for lesmana: 
baz

Смотрите файл, созданный в /var/run/sudo/username:

$ sudo ls -l /var/run/sudo/lesmana
total 0
-rw------- 1 root lesmana 0 2011-04-25 16:56 1
-rw------- 1 root lesmana 0 2011-04-25 16:57 2
-rw------- 1 root lesmana 0 2011-04-25 16:58 tty1 # <-- new

Теперь давайте попробуем это с помощью вашего сценария оболочки. Я использовал тот же скрипт робота, что и в тексте вопроса.

$ ./robot
apple
banana

Нет запроса пароля, потому что я использовал первый терминал, в котором sudo все еще запоминает мой пароль.

Смотрите обновленный файл в /var/run/sudo/username:

$ sudo ls -l /var/run/sudo/lesmana
total 0
-rw------- 1 root lesmana 0 2011-04-25 17:01 1 # <-- timestamp update
-rw------- 1 root lesmana 0 2011-04-25 16:57 2
-rw------- 1 root lesmana 0 2011-04-25 16:58 tty1

Теперь давайте попробуем скрипт с перенаправлением:

$ ./robot > foo
[sudo] password for lesmana:

Обратите внимание, что sudo попросил пароль.

Проверьте /var/run/sudo/username:

$ sudo ls -l /var/run/sudo/lesmana
total 0
-rw------- 1 root lesmana 0 2011-04-25 17:01 1
-rw------- 1 root lesmana 0 2011-04-25 16:57 2
-rw------- 1 root lesmana 0 2011-04-25 16:58 tty1
-rw------- 1 root lesmana 0 2011-04-25 17:02 unknown # <-- new

Смотрите этот unknown файл. По какой-то причине sudo больше не может определять терминал при выполнении в скрипте с перенаправленными потоками. Вот почему sudo запрашивает ваш пароль.

Обратите внимание, что в вашей системе sudo запрашивает пароль только после перенаправления как stdout, так и stderr. В моей системе (Ubuntu 10.04) sudo попросил пароль, когда я перенаправил стандартный вывод. Я понятия не имею, почему есть такая разница.

Также обратите внимание, что вы можете заставить sudo немедленно забыть свою аутентификацию с помощью команды sudo -k . Это забудет только аутентификацию для терминала, на котором была выполнена команда.

2

Он читает и пишет в /dev/tty , который всегда подключается к текущему tty/pty.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .