J'ai écrit un script qui prend comme argument une chaîne qui est une concaténation d'un nom d'utilisateur et d'un projet. Le script est supposé basculer (su) sur le nom d'utilisateur, cd sur un répertoire spécifique en fonction de la chaîne de projet.
Je veux fondamentalement faire:
su $USERNAME;
cd /home/$USERNAME/$PROJECT;
svn update;
Le problème est qu'une fois que je fais un su ... il attend juste là. Cela a du sens puisque le flux d’exécution est passé à la commutation vers l’utilisateur. Une fois que je sors, le reste des choses s'exécutent mais cela ne fonctionne pas comme souhaité.
J'ai préfixé su à la commande svn mais la commande a échoué (c'est-à-dire qu'elle n'a pas mis à jour svn dans le répertoire souhaité).
Comment puis-je écrire un script qui permet à l'utilisateur de changer d'utilisateur et d'appeler svn (entre autres choses)?
L'astuce consiste à utiliser la commande "Sudo" au lieu de "su"
Vous devrez peut-être ajouter ceci
username1 ALL=(username2) NOPASSWD: /path/to/svn
dans votre fichier/etc/sudoers
et changez votre script pour:
Sudo -u username2 -H sh -c "cd /home/$USERNAME/$PROJECT; svn update"
Où nomutilisateur2 correspond à l'utilisateur pour lequel vous souhaitez exécuter la commande SVN et nomutilisateur1 à l'utilisateur exécutant le script.
Si vous avez besoin de plusieurs utilisateurs pour exécuter ce script, utilisez un %groupname
au lieu du nom d'utilisateur1
Beaucoup plus simple: utilisez Sudo
pour exécuter un shell et utilisez un heredoc pour le nourrir.
#!/usr/bin/env bash
whoami
Sudo -i -u someuser bash << EOF
echo "In"
whoami
EOF
echo "Out"
whoami
(réponse à l'origine sur SuperUser )
Utilisez un script comme celui-ci pour exécuter le reste ou une partie du script sous un autre utilisateur:
#!/bin/sh
id
exec Sudo -u transmission /bin/sh - << eof
id
eof
Vous devez exécuter toutes les commandes d'utilisateur différent en tant que leur propre script. S'il ne s'agit que d'une ou de quelques commandes, alors inline devrait fonctionner. S'il y a beaucoup de commandes, il est probablement préférable de les déplacer dans leur propre fichier.
su -c "cd /home/$USERNAME/$PROJECT ; svn update" -m "$USERNAME"
Voici encore une autre approche, qui était plus pratique dans mon cas (je voulais simplement supprimer les privilèges root et faire le reste de mon script à partir d'un utilisateur restreint): vous pouvez faire en sorte que le script redémarre de l'utilisateur correct. Supposons qu'il soit initialement lancé en tant que root. Ensuite, cela ressemblera à ceci:
#!/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"
...
Utilisez Sudo
à la place
EDIT : Comme l'a souligné Douglas, vous ne pouvez pas utiliser cd
dans Sudo
car ce n'est pas un commande externe . Vous devez exécuter les commandes dans un sous-shell pour que le cd
fonctionne.
Sudo -u $USERNAME -H sh -c "cd ~/$PROJECT; svn update"
Sudo -u $USERNAME -H cd ~/$PROJECT Sudo -u $USERNAME svn update
Vous pouvez être invité à saisir le mot de passe de cet utilisateur, mais une seule fois.
Il n'est pas possible de changer d'utilisateur dans un script Shell. Les solutions de contournement utilisant Sudo décrites dans d’autres réponses sont probablement votre meilleur choix.
Si vous êtes assez fou pour exécuter des scripts Perl en tant que root, vous pouvez le faire avec les variables $< $( $> $)
qui contiennent les uid/gid réels/effectifs, par exemple:
#!/usr/bin/Perl -w
$user = shift;
if (!$<) {
$> = getpwnam $user;
$) = getgrnam $user;
} else {
die 'must be root to change uid';
}
system('whoami');
Cela a fonctionné pour moi
Je sépare mon "provisioning" de mon "démarrage".
# Configure everything else ready to run
config.vm.provision :Shell, path: "provision.sh"
config.vm.provision :Shell, path: "start_env.sh", run: "always"
puis dans mon 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 &