Как запускать интерактивные команды от имени другого пользователя

Как запускать интерактивные команды от имени другого пользователя

Я пытаюсь написать 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, и это единственная цель suas 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

Должно сработать. Настройте это под свои нужды, но это переключит контексты, и статус возврата оболочки будет в том же состоянии, $?когда вы закончите с этим.

Связанный контент