Come si usa su di eseguire il resto dello script bash come tale utente?
-
22-09-2019 - |
Domanda
Ho scritto uno script che prende, come argomento, una stringa che è una concatenazione di un nome utente e un progetto. Lo script dovrebbe passare (su) al nome utente, cd in una directory specifica in base alla stringa di progetto.
Io fondamentalmente voglio fare:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
Il problema è che una volta che faccio un do ... semplicemente aspetta lì. Che ha senso in quanto il flusso di esecuzione è passata alla commutazione per l'utente. Una volta esco, poi il resto delle cose eseguire, ma non funziona, se lo desideri.
I anteposto su al comando svn, ma il comando non riuscito (vale a dire che non ha aggiornato svn nella directory desiderata).
Come faccio a scrivere uno script che permette all'utente di passare utente e richiamare svn (tra le altre cose)?
Soluzione
Il trucco è quello di utilizzare il comando "sudo" al posto di "su"
Potrebbe essere necessario aggiungere questo
username1 ALL=(username2) NOPASSWD: /path/to/svn
per file / etc / sudoers
e modificare lo script a:
sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
Dove nomeutente2 è l'utente che si desidera eseguire il comando SVN, come e username1 è l'utente esegue lo script.
Se avete bisogno di più utenti di eseguire questo script, utilizzare un %groupname
al posto del username1
Altri suggerimenti
Molto più semplice: l'uso sudo
per eseguire una shell e utilizzare un heredoc per nutrire comanda.
#!/usr/bin/env bash
whoami
sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
Utilizzare uno script come il seguente per eseguire il riposo o parte dello script in un altro utente:
#!/bin/sh
id
exec sudo -u transmission /bin/sh - << eof
id
eof
È necessario eseguire tutti i comandi diversi utenti come proprio script. Se è solo uno, o alcuni comandi, quindi in linea dovrebbe funzionare. Se si tratta di un sacco di comandi, allora è probabilmente meglio per spostarli al proprio file.
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
Ecco un altro approccio, che era più conveniente nel mio caso (Volevo solo far cadere i privilegi di root e fare il resto del mio script da utente con accesso limitato): è possibile effettuare lo script di riavvio se stesso da utente corretto. Supponiamo che viene eseguito come root inizialmente. Poi sarà simile a questa:
#!/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"
...
Usa sudo
invece
Modifica : Come Douglas ha sottolineato, non è possibile utilizzare cd
in sudo
in quanto non è un esterna comando. È necessario eseguire i comandi in una subshell per far funzionare il cd
.
sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
sudo -u $USERNAME -H cd ~/$PROJECT
sudo -u $USERNAME svn update
È possibile che venga chiesto di inserire tale password dell'utente, ma solo una volta.
Non è possibile cambiare utente all'interno di uno script di shell. Soluzioni alternative che utilizzano sudo descritto in altre risposte sono probabilmente la soluzione migliore.
Se siete abbastanza pazzi per eseguire script Perl come root, si può fare questo con le variabili che tengono $< $( $> $)
reale / uid / gid effettivo, per esempio:.
#!/usr/bin/perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
Questo ha funzionato per me
ho diviso il mio "provisioning" dal mio "startup".
# Configure everything else ready to run
config.vm.provision :shell, path: "provision.sh"
config.vm.provision :shell, path: "start_env.sh", run: "always"
poi nella mia 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 &
ispira l'idea da @ MarSoft ma ho cambiato le linee come le seguenti:
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
Ho usato sudo
per consentire una password meno l'esecuzione dello script. Se si vuole inserire una password per l'utente, rimuovere il sudo
. Se non avete bisogno le variabili di ambiente, togliere -E
da sudo.
Il /usr/bin/bash -l
assicura che gli script profile.d
vengono eseguiti per un ambiente inizializzata.