¿Cómo uso su para ejecutar el rest del script bash como ese usuario?

He escrito un script que toma, como argumento, una cadena que es una concatenación de un nombre de usuario y un proyecto. Se supone que el script cambia (su) al nombre de usuario, cd a un directorio específico basado en la cadena del proyecto.

Básicamente quiero hacer:

su $USERNAME; cd /home/$USERNAME/$PROJECT; svn update; 

El problema es que una vez que hago un su … simplemente espera allí. Lo cual tiene sentido ya que el flujo de ejecución ha pasado al cambio al usuario. Una vez que salgo, el rest de las cosas se ejecutan pero no funciona como se desea.

Agregué su al comando svn pero el comando falló (es decir, no actualizó svn en el directorio deseado).

¿Cómo escribo un script que permite al usuario cambiar de usuario e invocar svn (entre otras cosas)?

El truco es usar el comando “sudo” en lugar de “su”

Es posible que deba agregar esto

 username1 ALL=(username2) NOPASSWD: /path/to/svn 

a su archivo / etc / sudoers

y cambia tu script a:

 sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update" 

Donde username2 es el usuario que desea ejecutar el comando SVN, y username1 es el usuario que ejecuta el script.

Si necesita varios usuarios para ejecutar este script, use un %groupname lugar del username1

Mucho más simple: use sudo para ejecutar un shell y use un heredoc para alimentarlo.

 #!/bin/bash whoami sudo -u someuser bash << EOF echo "In" whoami EOF echo "Out" whoami 

(respuesta originalmente en SuperUser )

Use una secuencia de comandos como la siguiente para ejecutar el rest o parte de la secuencia de comandos en otro usuario:

 #!/bin/sh id exec sudo -u transmission /bin/sh - << eof id eof 

Debe ejecutar todos los comandos de usuario diferente como su propio script. Si solo son uno o unos pocos comandos, entonces debe funcionar en línea. Si son muchos comandos, probablemente sea mejor moverlos a su propio archivo.

 su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME" 

Aquí hay otro enfoque, que era más conveniente en mi caso (solo quería dejar privilegios de root y hacer el rest de mi script del usuario restringido): puede hacer que la secuencia de comandos se reinicie desde el usuario correcto. Supongamos que se ejecuta como raíz inicialmente. Entonces se verá así:

 #!/bin/bash if [ $UID -eq 0 ]; then user=$1 dir=$2 shift 2 # if you need some other parameters cd "$dir" exec su "$user" "$0" "$@" # nothing will be executed beyond that line, # because exec replaces running process with the new one fi echo "This will be run from user $UID" ... 

Use sudo lugar

EDITAR : Como señaló Douglas, no puedes usar cd en sudo ya que no es un comando externo . Tienes que ejecutar los comandos en una subshell para hacer que el cd funcione.

 sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update" 

 sudo -u $USERNAME -H cd ~/$PROJECT sudo -u $USERNAME svn update 

Se le puede pedir que ingrese la contraseña de ese usuario, pero solo una vez.

No es posible cambiar el usuario dentro de un script de shell. Las soluciones alternativas que usan sudo descrito en otras respuestas son probablemente su mejor opción.

Si estás lo suficientemente loco como para ejecutar scripts Perl como root, puedes hacer esto con las variables $< $( $> $) que contienen el uid / gid real / efectivo, por ejemplo:

 #!/usr/bin/perl -w $user = shift; if (!$<) { $> = getpwnam $user; $) = getgrnam $user; } else { die 'must be root to change uid'; } system('whoami'); 

Esto funcionó para mí

Dividí mi “aprovisionamiento” de mi “inicio”.

  # Configure everything else ready to run config.vm.provision :shell, path: "provision.sh" config.vm.provision :shell, path: "start_env.sh", run: "always" 

luego en mi start_env.sh

 #!/usr/bin/env bash echo "Starting Server Env" #java -jar /usr/lib/node_modules/selenium-server-standalone-jar/jar/selenium-server-standalone-2.40.0.jar & #(cd /vagrant_projects/myproj && sudo -u vagrant -H sh -c "nohup npm install 0<&- &>/dev/null &;bower install 0<&- &>/dev/null &") cd /vagrant_projects/myproj nohup grunt connect:server:keepalive 0<&- &>/dev/null & nohup apimocker -c /vagrant_projects/myproj/mock_api_data/config.json 0<&- &>/dev/null & 

Inspirado por la idea de @ MarSoft pero cambié las líneas de la siguiente manera:

 USERNAME='desireduser' COMMAND=$0 COMMANDARGS="$(printf " %q" "${@}")" if [ $(whoami) != "$USERNAME" ]; then exec sudo -E su $USERNAME -c "/usr/bin/bash -l $COMMAND $COMMANDARGS" exit fi 

He usado sudo para permitir una contraseña con menos ejecución del script. Si desea ingresar una contraseña para el usuario, elimine el sudo . Si no necesita las variables de entorno, elimine -E de sudo.

El /usr/bin/bash -l asegura que las secuencias de comandos profile.d se ejecutan para un entorno inicializado.