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?

47
demandé sur Andrew 2013-12-11 00:35:29

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 via sudo.
  • ce qui suit est basé sur la configuration par défaut de sudo - changer sa configuration peut le faire se comporter différemment-voir man 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 pour someUser, 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 de someUser, 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.
  • -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.

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 accepte sudo -u root -s 'echo $SHELL - $USER - $HOME - $PWD' directement (pas besoin de eval), alors que Linux ne le fait pas (à partir de sudo 1.8.95p).

  • Les anciennes versions de sudo sous Linux n'appliquent pas d'extensions shell aux arguments passés à un shell ; par exemple, avec sudo 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 moins sudo 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 de sudo, 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.

75
répondu mklement0 2016-12-09 03:21:06

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é.

21
répondu David W. 2013-12-10 21:29:24

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)

14
répondu TrinitronX 2015-01-29 06:29:07

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.

3
répondu chooban 2013-12-10 21:09:43

Donc, vous voulez:

  1. exécute une partie d'un script bash en tant qu'utilisateur différent
  2. 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
2
répondu Michael Kropat 2017-05-23 12:26:38

Cela fonctionne sous Linux. Je ne sais pas comment il se comporte dans d'autres * nixes .

  getent passwd "${OTHER_USER}"|cut -d\: -f 6
2
répondu hydrian 2016-08-19 16:59:38

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

0
répondu Grizly 2014-12-28 23:18:45

Rapide et sale, et stockez - le dans une variable:

USER=somebody
USER_HOME="$(echo -n $(bash -c "cd ~${USER} && pwd"))"
0
répondu cobbzilla 2015-03-05 07:39:52

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!

0
répondu Quote 2016-09-24 00:14:48

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'"
0
répondu Elifarley 2017-03-31 13:04:32