Comment obtenir le répertoire $ HOME d'un utilisateur différent dans le script bash ?
J'ai besoin d'exécuter une partie d'un script bash en tant qu'utilisateur différent, et dans le répertoire $HOME
de cet utilisateur. Cependant, je ne sais pas comment déterminer cette variable. Passer à cet utilisateur et appeler $HOME
ne fournit pas l'emplacement correct:
# running script as root, but switching to a different user...
su - $different_user
echo $HOME
# returns /root/ but should be /home/myuser
Mise à jour:
Il semble que le problème soit avec la façon dont j'essaie de changer d'utilisateur dans mon script:
$different_user=deploy
# create user
useradd -m -s /bin/bash $different_user
echo "Current user: `whoami`"
# Current user: root
echo "Switching user to $different_user"
# Switching user to deploy
su - $different_user
echo "Current user: `whoami`"
# Current user: root
echo "Current user: `id`"
# Current user: uid=0(root) gid=0(root) groups=0(root)
sudo su $different_user
# Current user: root
# Current user: uid=0(root) gid=0(root) groups=0(root)
Quelle est la bonne façon de changer d'utilisateur et d'exécuter des commandes en tant qu'utilisateur différent dans un script bash?
10 réponses
Update : sur la base du titre de cette question, les gens semblent venir ici juste à la recherche d'un moyen de trouver le répertoire personnel d'un utilisateur différent, sans avoir besoin de usurper l'identité de cet utilisateur.
Dans ce cas, la solution la plus simple est d'utiliser tilde expansion avec le nom d'utilisateur d'intérêt, combiné avec eval
(Ce Qui est nécessaire, car le nom d'utilisateur doit être donné en tant que littéral non cité pour l'expansion du tilde pour travailler):
eval echo "~$different_user" # prints $different_user's home dir.
Remarque: La habitude mises en garde concernant l'utilisation de eval
appliquer; dans ce cas, l'hypothèse est que vous pouvez contrôler la valeur de $different_user
et savent que c'est un simple nom d'utilisateur.
En revanche, le reste de cette réponse traite usurpation de l'identité d' un utilisateur et effectuer des opérations que dans le répertoire home de l'utilisateur.
Remarque:
- administrateurs par défaut et autres utilisateurs si autorisé par la
sudoers
fichier peut usurper l'identité d'autres utilisateurs viasudo
. - ce qui suit est basé sur la configuration par défaut de
sudo
- changer sa configuration peut le faire se comporter différemment-voirman sudoers
.
La forme de base d'exécution d'une commande en tant qu'autre utilisateur est:
sudo -H -u someUser someExe [arg1 ...]
# Example:
sudo -H -u root env # print the root user's environment
Remarque:
-
si vous négligez de spécifier
-H
, le processus d'usurpation d'identité (le processus invoqué dans le contexte de l'utilisateur spécifié) signalez le répertoire personnel de l'utilisateur original dans$HOME
. - le processus d'usurpation d'identité aura le même répertoire de travail que le processus d'appel.
- le processus d'usurpation d'identité effectue aucune expansion de shell sur les littéraux de chaîne passés comme arguments, car aucun shell n'est impliqué dans le processus d'usurpation d'identité (sauf si
someExe
se trouve être un shell) - les expansions par le shell appelant - avant de passer au processus d'usurpation d'identité - encore se produire.
En option, vous pouvez avoir un processus d'usurpation d'identité exécuté en tant que ou via un shell(n usurpation d'identité) , en préfixant someExe
soit avec -i
ou -s
- ne pas spécifier someExe ...
crée un shellinteractif :
-
-i
crée un login shell poursomeUser
, ce qui implique la suivante:-
Le profil shell spécifique à l'utilisateur de
someUser
, s'il est défini, est chargé . -
$HOME
pointe vers Le répertoire personnel desomeUser
, donc il n'y a pas besoin de-H
( bien que vous puissiez toujours le spécifier) - le répertoire de travail de l'interpréteur de commandes est le répertoire personnel de
someUser
.
-
Le profil shell spécifique à l'utilisateur de
-
-s
crée un shell sans connexion:- aucun shell profile n'est chargé (bien que les fichiers d'initialisation pour les shells interactifs nonlogin Le soient; par exemple,
~/.bashrc
) -
sauf si vous spécifiez également
-H
, le processus d'usurpation d'identité signalez le répertoire personnel de l'utilisateur original dans$HOME
. - le shell usurpateur aura le même répertoire de travail que le processus appelant.
- aucun shell profile n'est chargé (bien que les fichiers d'initialisation pour les shells interactifs nonlogin Le soient; par exemple,
L'utilisation d'un shell signifie que les arguments de chaîne transmis sur la ligne de commande peuvent être soumis à des expansions de shell - voir différences spécifiques à la plate-forme ci-dessous - par le shell usurpateur (éventuellement après l'expansion initiale par le shell appelant); comparez les deux suivantes commandes (qui utilisent guillemets simples pour empêcher l'expansion prématurée par le shell appelant ):
# Run root's shell profile, change to root's home dir.
sudo -u root -i eval 'echo $SHELL - $USER - $HOME - $PWD'
# Don't run root's shell profile, use current working dir.
# Note the required -H to define $HOME as root`s home dir.
sudo -u root -H -s eval 'echo $SHELL - $USER - $HOME - $PWD'
Quel shell est appelé est déterminé par "la variable D'environnement SHELL si elle est définie ou le shell comme spécifié dans passwd (5)" (selon man sudo
). Notez qu'avec -s
, il est le invoquant utilisateur de l'environnement de questions, alors qu'avec -i
, il est le représenté de l'utilisateur.
Notez qu'il existe une plate-forme différences concernant le comportement lié au shell (avec -i
ou -s
):
sudo
sous Linux, apparemment, n'accepte qu'un nom exécutable ou intégré comme premier argument suivant-s
/-i
, alors QU'OSX permet de passer une ligne de commande shell entière; par exemple, OSX acceptesudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD'
directement (pas besoin deeval
), alors que Linux ne le fait pas (à partir desudo 1.8.95p
).Les anciennes versions de
sudo
sous Linux n'appliquent pas d'extensions shell aux arguments passés à un shell ; par exemple, avecsudo 1.8.3p1
(par exemple, Ubuntu 12.04),sudo -u root -H -s echo '$HOME'
fait simplement écho au littéral de chaîne "$HOME " au lieu d'étendre la référence de variable dans le contexte de l'utilisateur root. Depuis au moinssudo 1.8.9p5
(par exemple, Ubuntu 14.04), cela a été corrigé. Par conséquent, pour assurer L'expansion sur Linux même avec les anciennes versions desudo
, passez la commande entière en tant qu'argument unique àeval
; par exemple:sudo -u root -H -s eval 'echo $HOME'
. (Bien que pas nécessaire sur OSX, cela fonctionnera là-bas, trop.)La variable
root
de l'utilisateur$SHELL
contient/bin/sh
sur OSX 10.9, alors qu'elle est/bin/bash
sur Ubuntu 12.04.
Que le processus d'usurpation d'identité implique ou non un shell, son environnement aura les variables suivantes, reflétant l'utilisateur et la commande appelant: SUDO_COMMAND
, SUDO_USER
, SUDO_UID=
, SUDO_GID
.
Voir man sudo
et man sudoers
pour beaucoup plus de subtilités.
Astuce du chapeau à @ DavidW et @ Andrew pour l'inspiration.
Dans BASH, vous pouvez trouver le répertoire $HOME
d'un utilisateur en préfixant son identifiant de connexion par un caractère tilde. Par exemple:
$ echo ~bob
Cela fera écho au répertoire $HOME
de l'utilisateur bob
.
Cependant, vous dites que vous voulez pouvoir exécuter un script en tant qu'utilisateur particulier. Pour ce faire, vous devez configurer sudo. Cette commande vous permet d'exécuter des commandes particulières en tant qu'utilisateur particulier. Par exemple, pour exécuter foo
en tant qu'utilisateur bob
:
$ sudo -i -ubob -sfoo
Cela va commencer un nouveau shell, et le -i
simulera une connexion avec l'environnement et le shell par défaut de l'utilisateur (ce qui signifie que la commande foo
s'exécutera à partir du répertoire bob's
$HOME`.)
Sudo est un peu complexe à configurer, et vous devez être un superutilisateur juste pour pouvoir voir le fichier shudders (généralement /etc/sudoers
). Toutefois, ce fichier a généralement plusieurs exemples que vous pouvez utiliser.
Dans ce fichier, vous pouvez spécifier les commandes que vous spécifiez qui peut exécuter une commande, en tant qu'utilisateur et si oui ou non cet utilisateur doit entrer son mot de passe avant d'exécuter cette commande. C'est normalement la valeur par défaut (car cela prouve que c'est l'utilisateur et non quelqu'un qui est venu pendant que l'utilisateur recevait un Coca.) Cependant, lorsque vous exécutez un script shell, vous souhaitez généralement désactiver cette fonctionnalité.
Par souci d'une réponse alternative pour ceux qui recherchent un moyen léger de trouver simplement le répertoire d'accueil d'un utilisateur...
Plutôt que de jouer avec su
hacks, ou de se soucier de la surcharge de lancer un autre shell bash
juste pour trouver la variable d'environnement $HOME
...
Léger Simple Homedir requête via Bash
Il existe une commande spécialement pour ce: getent
getent passwd someuser | cut -f6 -d:
getent
peut faire beaucoup plus... il suffit de voir le homme page . La base de données passwd
nsswitch renverra l'entrée de l'utilisateur au format /etc/passwd
. Il suffit de le diviser sur le côlon :
pour analyser les champs.
Il devrait être installé sur la plupart des systèmes Linux (ou tout système qui utiliseGNU Lib C (RHEL: glibc-common
, Deb: libc-bin
)
Vous voulez l'option -u
pour sudo
dans ce cas. De la page man
:
The -u (user) option causes sudo to run the specified command as a user other than root.
Si vous n'avez pas besoin de l'exécuter en tant que, vous pourriez passer à leur répertoire ~<user>
. Comme dans, pour vous déplacer dans mon répertoire personnel, vous utiliseriez cd ~chooban
.
Donc, vous voulez:
- exécute une partie d'un script bash en tant qu'utilisateur différent
- modifier le répertoire $HOME de cet utilisateur
Inspiré par cette réponse, voici la version adaptée de votre script:
#!/usr/bin/env bash
different_user=deploy
useradd -m -s /bin/bash "$different_user"
echo "Current user: $(whoami)"
echo "Current directory: $(pwd)"
echo
echo "Switching user to $different_user"
sudo -u "$different_user" -i /bin/bash - <<-'EOF'
echo "Current user: $(id)"
echo "Current directory: $(pwd)"
EOF
echo
echo "Switched back to $(whoami)"
different_user_home="$(eval echo ~"$different_user")"
echo "$different_user home directory: $different_user_home"
Lorsque vous l'exécutez, vous devriez obtenir la suivante:
Current user: root
Current directory: /root
Switching user to deploy
Current user: uid=1003(deploy) gid=1003(deploy) groups=1003(deploy)
Current directory: /home/deploy
Switched back to root
deploy home directory: /home/deploy
Cela fonctionne sous Linux. Je ne sais pas comment il se comporte dans d'autres * nixes .
getent passwd "${OTHER_USER}"|cut -d\: -f 6
Je cherchais aussi cela, mais je ne voulais pas usurper l'identité d'un utilisateur pour simplement acquérir un chemin!
user_path=$(grep $username /etc/passwd|cut -f6 -d":");
Maintenant, dans votre script, vous pouvez vous référer à $user_path
dans la plupart des cas, il serait /home/username
Suppose: vous avez précédemment défini $username
avec la valeur du nom d'Utilisateur des utilisateurs prévus.
Source: http://www.unix.com/shell-programming-and-scripting/171782-cut-fields-etc-passwd-file-into-variables.html
Rapide et sale, et stockez - le dans une variable:
USER=somebody
USER_HOME="$(echo -n $(bash -c "cd ~${USER} && pwd"))"
J'étais aux prises avec cette question parce que je cherchais un moyen de le faire dans un script bash pour OS X, donc /etc/passwd était hors de question, et mon script était censé être exécuté en tant que root, rendant donc les solutions invoquant eval ou bash-c dangereuses car elles permettaient l'injection de code dans la variable spécifiant
Voici ce que j'ai trouvé. C'est simple et ne met pas une variable dans un sous-shell. Cependant il nécessite que le script soit exécuté par root car il sudos dans le compte d'utilisateur spécifié.
En supposant que $ SOMEUSER contient un nom d'utilisateur valide:
echo "$(sudo -H -u "$SOMEUSER" -s -- "cd ~ && pwd")"
J'espère que cela aide quelqu'un!
Si l'utilisateur n'existe pas, getent
retournera une erreur.
Voici une petite coquille fonction qui n'ignorent pas le code de sortie de getent
:
get_home() {
local result; result="$(getent passwd "$1")" || return
echo $result | cut -d : -f 6
}
Voici un exemple d'utilisation:
da_home="$(get_home missing_user)" || {
echo 'User does NOT exist!'; exit 1
}
# Now do something with $da_home
echo "Home directory is: '$da_home'"