
Я пытаюсь написать bash-скрипт, который
- контекст переключается на другого пользователя (в данном случае root)
- выполняет набор команд дляя.создайте пользователя (интерактивно запрашивая у вызывающего имя пользователя), затемii.устанавливает пароль для этого пользователя
- получает возвращаемое значение
- затем продолжает выполнять действия с возвращаемым значением
До сих пор я пробовал вводить << EOF (рисунок 1), функция (рис.2), и извлечение / запуск отдельного скрипта (рис.3). Однако я не получил нужных мне результатов.
sudo su - << 'EOF'
# do stuff...
EOF
рисунок 1
function myfunc()
{
local myresult='some value'
echo "$myresult"
}
рис.2
sudo su - -c bash <(curl -fksSL https://<my-script-location>.sh)
рис.3
решение1
sudo su - << 'EOF' # do stuff... EOF
Это работает, но с ограничением: скрипт передается оболочке на ее стандартный ввод, поэтому вы не можете использовать стандартный ввод для чего-то еще, например, для чтения имени пользователя, которого нужно создать.
Самый простой способ сохранить стандартный ввод — передать команду оболочки в качестве аргумента.
Обратите внимание, что sudo su
это избыточно — sudo
запускает указанную команду как root, и это единственная цель su
as well. Используйте sudo -i
вместо sudo su -
, если вы хотите запустить оболочку входа как root — что, вероятно, здесь не нужно — или sudo sh
просто запустить оболочку как root.
sudo sh -c '
# do stuff...
'
Это делает неудобным использование одинарной кавычки в фрагменте оболочки. Вы можете использовать '\''
для помещения одинарной кавычки внутрь литерала в одинарных кавычках. Если вы хотите сохранить структуру документа here, есть несколько способов. Самый простой — передать документ hereпо другому дескриптору. Однако для этого необходимо closefrom_override
активировать эту опцию в конфигурации sudo, что по умолчанию не предусмотрено; по умолчанию sudo
закрывает все файловые дескрипторы, кроме stdin, stdout и stderr.
sudo -C 3 sh -c '. /dev/fd/3' 3<<'EOF'
# do stuff...
EOF
Если вы хотите, чтобы ваш код был переносим на машины, где эта опция не активирована, вы можете прочитать скрипт из heredoc и передать его оболочке в качестве аргумента.
script=$(cat <<'EOF'
# do stuff...
EOF
)
sudo sh -c "$script"
В качестве альтернативы, если вы хотите, чтобы скрипт sudoed мог читать с терминала, вы можете передать тело скрипта на стандартный ввод. Ограничением этого подхода является то, что он не позволяет перенаправлять ввод всего скрипта.
sudo sh <<'EOF'
exec </dev/tty
# do stuff...
EOF
решение2
При условии, что вызывающий пользователь sudo
может выделить tty
:
Defaults someuser:requiretty
ans получил разрешения на выполнение необходимых команд от имени пользователя root:
Cmnd_Alias STUFF = /usr/bin/passwd, /usr/sbin/useradd
someuser ALL = STUFF
скрипт, содержащий sudo
вызовы, будет интерактивным. Вы можете передать имя пользователя как позиционный аргумент:
sudo useradd $1
sudo passwd $1
и проверьте статус возврата как обычно с помощью $?
.
решение3
su -c '. /dev/fd/4' 4<<\SCRIPT
...automated stuff here...
....then for interactive...
exec </dev/tty
SCRIPT
Должно сработать. Настройте это под свои нужды, но это переключит контексты, и статус возврата оболочки будет в том же состоянии, $?
когда вы закончите с этим.