Cómo ejecutar comandos interactivos, como otro usuario

Cómo ejecutar comandos interactivos, como otro usuario

Estoy intentando escribir un script bash que

  • el contexto cambia a otro usuario (root, en este caso)
  • ejecuta un conjunto de comandos parai.cree un usuario (solicitando interactivamente al invocador el nombre de usuario) y luegoii.establece la contraseña de ese usuario
  • obtiene un valor de retorno
  • luego continúa haciendo cosas, con ese valor de retorno

Hasta ahora he probado una entrada << EOF (Figura 1), Una función (Figura 2), y extraer/ejecutar un script separado (Fig. 3). Sin embargo no he obtenido los resultados que necesito.

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

Figura 1

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

Figura 2

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

Fig. 3

Respuesta1

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

Esto funciona, pero con una limitación: el script se pasa al shell en su entrada estándar, por lo que no puedes usar la entrada estándar para otra cosa, como leer el nombre del usuario a crear.

La forma sencilla de conservar la entrada estándar es pasar el comando de shell como argumento.

Tenga en cuenta que sudo sues redundante: ejecuta el comando especificado como root, y ese también sudoes el único propósito . suÚselo sudo -ien lugar de sudo su -si desea ejecutar un shell de inicio de sesión como root (lo cual probablemente no sea necesario aquí) o sudo shsimplemente ejecutar un shell como root.

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

Esto hace que sea incómodo utilizar una comilla simple en el fragmento de shell. Puedes usar'\'' para poner una comilla simple dentro del literal entre comillas simples. Si desea conservar la estructura del documento aquí, existen varias formas. Lo más sencillo es pasar el documento aquí.en un descriptor diferente. Sin embargo, esto requiere que la closefrom_overrideopción esté activada en la configuración de sudo, lo cual no es el caso por defecto; de forma predeterminada, sudocierra todos los descriptores de archivos distintos de stdin, stdout y stderr.

sudo -C 3 sh -c '. /dev/fd/3' 3<<'EOF'
# do stuff...
EOF

Si desea que su código sea portátil para máquinas donde esta opción no está activada, puede leer el script desde un heredoc y pasarlo al shell como argumento.

script=$(cat <<'EOF'
# do stuff...
EOF
)
sudo sh -c "$script"

Alternativamente, si desea que el script sudo pueda leerse desde la terminal, puede pasar el cuerpo del script en la entrada estándar. Una limitación de este enfoque es que no permite redirigir la entrada del script general.

sudo sh <<'EOF'
exec </dev/tty
# do stuff...
EOF

Respuesta2

Siempre que el usuario que invoca sudopueda asignar un tty:

Defaults someuser:requiretty

A ans se le han otorgado permisos para ejecutar los comandos necesarios como root:

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

un script que contenga sudoinvocaciones será interactivo. Podrías pasar el nombre de usuario como argumento posicional:

sudo useradd $1
sudo passwd $1

y verifique el estado de la devolución como de costumbre con $?.

Respuesta3

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

Deberías hacerlo. Adapte esto para satisfacer sus necesidades, pero cambiará de contexto y el estado de retorno del shell será el mismo $?cuando haya terminado.

información relacionada