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()