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

Я пытаюсь написать сценарий bash, который

  • контекст переключается на другого пользователя (root в этом случае)
  • выполняет набор команд для i. создайте пользователя (интерактивно запрашивая invoker для имени пользователя), затем ii. устанавливает пароль для этого пользователя
  • получает возвращаемое значение
  • затем продолжает делать вещи, причем это возвращаемое значение

Я до сих пор пробовал << вход EOF ( рис.1 ), функцию ( рис. 2 ) и вытягивание / запуск отдельного скрипта ( рис. 3 ). Однако я не получил результатов, которые мне нужны. Любая помощь здесь? Надеюсь, я ясно объяснил это.

sudo su - << 'EOF' # do stuff... EOF 

рисунок 1

 function myfunc() { local myresult='some value' echo "$myresult" } 

fig.2

 sudo su - -c bash <(curl -fksSL https://<my-script-location>.sh) 

рис.3

 sudo su - << 'EOF' # do stuff... EOF 

Это работает, но с ограничением: скрипт передается оболочке на стандартный ввод, поэтому вы не можете использовать стандартный ввод для чего-то еще, например, для чтения имени создаваемого пользователя.

Простым способом сохранения стандартного ввода является передача команды оболочки в качестве аргумента.

Обратите внимание, что sudo su избыточно – sudo запускает указанную команду как root, и это единственная цель su . Используйте sudo -i вместо sudo su - если вы хотите запустить оболочку входа в систему как root, что, вероятно, здесь не нужно, или sudo sh чтобы запустить оболочку как root.

 sudo sh -c ' # do stuff... ' 

Это делает неудобным использование одной кавычки в фрагменте оболочки. Вы можете использовать '\'' чтобы поставить одну цитату внутри однокасканного литерала. Если вы хотите сохранить структуру документа здесь, существует несколько способов. Самый простой способ – передать этот документ на другой дескриптор . Однако для этого требуется, closefrom_override опция 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 

При условии, что пользователь, вызывающий sudo может выделить tty :

 Defaults someuser:requiretty 

ans было предоставлено разрешение на выполнение необходимых команд с правами root:

 Cmnd_Alias STUFF = /usr/bin/passwd, /usr/sbin/useradd someuser ALL = STUFF 

скрипт, содержащий sudo invocations, будет интерактивным. Вы можете передать имя пользователя в качестве позиционного аргумента:

 sudo useradd $1 sudo passwd $1 

и проверить статус возврата как обычно с помощью $? ,

 su -c '. /dev/fd/4' 4<<\SCRIPT ...automated stuff here... ....then for interactive... exec </dev/tty SCRIPT 

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