Bash: sudo -S <<< "mypassword" - проблема с интерактивной оболочкой
Я пытаюсь использовать sudo
с -S
выдать пароль через командную строку.
$ sudo -S <<< "mypassword" command
Это работает, но не допускает интерактивных команд. подобно nano
например:
$ sudo -S <<< "mypassword" nano /tmp/foo
Он автоматически закрывает нано-сессию. То же самое с apt-get
:
$ sudo -S <<< "mypassword" apt-get install foo
Он закрывается, прежде чем я могу нажать "y", чтобы установить foo. Я знаю, что могу пройти -y
с подходящим, но в целом, это расстраивает.
Также пробовал такие вещи, как это, но он по-прежнему не взаимодействует с интерактивной сессией
$ sudo -S <<< "mypassword" -H -u root bash -c "apt-get install foo"
Можно ли использовать -S
с sudo без отмены всех интерактивных оболочек?
1 ответ
Файловые дескрипторы наследуются
То, что вы используете, это <<<
здесь-строка, и этот тип перенаправления реализуется через временные файлы, которые немедленно отсоединяются (или удаляются). Зная также, что процессы наследуют файловые дескрипторы (и stdin среди них) 1 от родителя к потомку, когда sudo -S
выполняется, он читает свои входные данные из временного файла, который был передан вашей исходной оболочки (тот, который читает sudo -S
команда). Вы можете увидеть это в действии:
$ sudo -S bash -c 'ls -l /proc/self/fd/0' <<< "mypasswd"
lr-x------ 1 root root 64 Feb 26 13:12 /proc/self/fd/0 -> '/tmp/sh-thd.cUOOXU (deleted)'
Таким образом, nano
отчеты Too many errors from stdin
ошибка в таком случае. Что можно сделать, это вручную повторно подключить, где stdin
идет от.
$ sudo -S bash -c 'exec < /dev/tty; nano /tmp/foobar' <<< "mypasswd"
$ sudo -S bash -c 'nano /tmp/foobar < /dev/tty' <<< "mypasswd"
Любая из двух команд будет nano
правильно и другие команды, а также. /dev/tty
это специальный файл, представляющий текущее оконечное устройство, и это фактически то же самое, что stdin
"нормальной" интерактивной оболочки (и, конечно, я упрощаю это утверждение).
Еще одна вариация на тему $ sudo -S bash -c 'nano /tmp/foobar 0>&1' <<<"mypasswd"
, stdout
фактически указывает на то же терминальное устройство (если вы явно не предоставили перенаправление, чтобы иметь точку stdout где-либо еще). Таким образом, если мы сделаем stdin
указать, чтобы быть dup
лицензия stdout
, это фактически то же решение, что и выше. (И если вам интересно, почему я выделил dup
часть, это потому что dup2()
syscall является ответственным за все манипулирование файловыми дескрипторами под капотом)
предосторожность
Тем не менее, обратите внимание, что я не рекомендую использовать sudo -S
в интерактивной оболочке, так как пароли останутся в истории оболочки
$ sudo -S bash -c 'sleep 3m' <<< "ohnomypassword"
^C
$ history 2
2016 sudo -S bash -c 'sleep 3m' <<< "ohnomypassword"
2017 history 2
sudo -S
больше подходит для использования с другими процессами, где sudo -S
будет ожидать ввода через конвейер, в идеале от zenity --password
или же dialog --passwordbox "foobar text" 200 200
(см. extra1 и extra2 о диалоге).
1. Если файл открыт с O_CLOEXEC
флаг установлен, дочерний процесс или замещенный процесс, порожденный через execve()
Тип флага не будет иметь доступа к этому дескриптору файла - то есть он будет закрыт execve()