Comment obtenir le répertoire $ HOME de différents utilisateurs en script bash?

Je dois exécuter une partie d’un script bash en tant qu’utilisateur différent et dans le répertoire $HOME cet utilisateur. Cependant, je ne suis pas sûr de savoir 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 

Mettre à jour:

Il semble que le problème réside dans la manière 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 manière correcte de changer d’utilisateur et d’exécuter des commandes en tant qu’utilisateur différent dans un script bash?

Mise à jour : Sur la base du titre de cette question, les gens semblent venir ici simplement pour trouver un moyen de trouver le répertoire de base d’un autre utilisateur, sans avoir à emprunter l’identité de cet utilisateur .

Dans ce cas, la solution la plus simple consiste à utiliser l’ extension tilde avec le nom d’utilisateur concerné, associé à eval (ce qui est nécessaire, car le nom d’utilisateur doit être donné sous forme de littéral non coté pour que l’extension tilde fonctionne):

 eval echo "~$different_user" # prints $different_user's home dir. 

Note: Les mises en garde habituelles concernant l’utilisation de eval s’appliquent ; Dans ce cas, l’hypothèse est que vous contrôlez la valeur de $different_user et que vous savez qu’il s’agit d’un simple nom d’utilisateur.

En revanche, le rest de cette réponse concerne l’ usurpation d’ identité d’ un utilisateur et l’ exécution d’opérations dans le répertoire de base de cet utilisateur .


Remarque:

  • Les administrateurs par défaut et les autres utilisateurs autorisés via le fichier sudoers peuvent emprunter l’identité d’autres utilisateurs via sudo .
  • Ce qui suit est basé sur la configuration par défaut de sudo – modifier sa configuration peut le faire se comporter différemment – voir man sudoers .

La forme de base de l’exécution d’une commande en tant qu’autre utilisateur est la suivante:

 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’emprunt d’identité (le processus appelé dans le contexte de l’utilisateur spécifié) signalera le répertoire de base de l’ utilisateur d’origine dans $HOME .
  • Le processus d’emprunt d’identité aura le même répertoire de travail que le processus appelant.
  • Le processus d’imitation n’effectue aucune extension de shell sur les littéraux de chaîne passés en argument, car aucun shell n’intervient dans le processus d’emprunt d’identité (à moins que someExe ne soit un shell) – les expansions par le shell someExe avant le processus se produire.

En option, vous pouvez avoir un processus d’emprunt d’identité exécuté en tant que ou via un shell (en someExe identité) , en préfixant someExe avec -i ou -s – sans spécifier someExe ... crée un shell interactif :

  • -i crée un shell de connexion pour someUser , ce qui implique ce qui suit:

    • Le profil de shell spécifique à l’utilisateur de someUser , s’il est défini, est chargé .
    • $HOME pointe vers le someUser de someUser , il n’y a donc pas besoin de -H (bien que vous puissiez toujours le spécifier)
    • Le répertoire de travail du shell d’emprunt d’identité est le someUser de someUser de someUser .
  • -s crée un shell non connecté:

    • aucun profil de shell n’est chargé (bien que les fichiers d’initialisation pour les shells interactifs non- login soient, par exemple, ~/.bashrc )
    • À moins que vous ne spécifiiez également -H , le processus d’emprunt d’identité signalera le répertoire de base de l’ utilisateur d’origine dans $HOME .
    • Le shell empruntant l’identité 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 extensions de shellvoir les différences spécifiques à la plate-forme ci-dessous – par le shell d’emprunt d’identité (éventuellement après l’extension initiale du shell appelant); comparez les deux commandes suivantes (qui utilisent des guillemets simples pour empêcher une 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' 

Le shell appelé est déterminé par “la variable d’environnement SHELL si elle est définie ou le shell spécifié dans passwd (5)” (d’après man sudo ). Notez qu’avec l’ -s c’est l’environnement invoquant de l’ utilisateur qui compte, alors qu’avec l’ -i c’est l’utilisateur emprunté .

Notez qu’il existe des différences de plateforme en ce qui concerne le comportement lié au shell (avec -i ou -s ) :

  • sudo sous Linux n’accepte apparemment qu’un nom exécutable ou intégré comme premier argument après -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 d’ eval ), alors que Linux ne le fait pas (depuis sudo 1.8.95p ).

  • Les anciennes versions de sudo sous Linux NE appliquent PAS les extensions de shell aux arguments transmis à un shell ; par exemple, avec sudo 1.8.3p1 (par exemple, Ubuntu 12.04), sudo -u root -H -s echo '$HOME' simplement la chaîne littérale “$ HOME” au lieu d’étendre la référence de variable dans le contexte de l’utilisateur root . Au moins sudo 1.8.9p5 (par exemple, Ubuntu 14.04), ce sudo 1.8.9p5 a été corrigé. Par conséquent, pour assurer une extension sous Linux, même avec les anciennes versions de sudo , transmettez la commande entière en un seul argument à eval ; ex: sudo -u root -H -s eval 'echo $HOME' . (Bien que cela ne soit pas nécessaire sur OSX, cela fonctionnera aussi ici.)

  • La variable $SHELL utilisateur root contient /bin/sh sur OSX 10.9, alors qu’il s’agit de /bin/bash sur Ubuntu 12.04.

Que le processus d’emprunt d’identité implique un shell ou non, son environnement aura les variables suivantes, reflétant l’utilisateur invoquant et la commande: SUDO_COMMAND , SUDO_USER , SUDO_UID= , SUDO_GID .

Voir man sudo et man sudoers pour plus de subtilités.

Astuce du chapeau à @DavidW et @Andrew pour l’inspiration.

Dans BASH, vous pouvez trouver le répertoire $HOME un utilisateur en préfixant l’ID de connexion de l’utilisateur avec un caractère tilde. Par exemple:

 $ echo ~bob 

Cela fera écho au répertoire $HOME utilisateur bob .

Cependant, vous dites que vous souhaitez 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 tant qu’utilisateur bob :

 $ sudo -i -ubob -sfoo 

Cela démarrera un nouveau shell et -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 $ HOME de bob's ).

Sudo est un peu complexe à configurer et vous devez être un super-utilisateur pour pouvoir voir le fichier /etc/sudoers (généralement /etc/sudoers ). Cependant, ce fichier contient 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, quel utilisateur et si cet utilisateur doit ou non saisir 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 obtenait un Coca-Cola.) Cependant, lorsque vous exécutez un script shell, vous souhaitez généralement désactiver cette fonctionnalité.

Pour une réponse alternative à ceux qui recherchent un moyen léger de trouver le répertoire personnel d’un utilisateur …

Plutôt que de jouer avec des hackers, ou de se préoccuper de lancer un autre shell bash juste pour trouver la variable d’environnement $HOME

Homedir simple et léger via Bash

Il y a une commande spécifiquement pour cela: getent

getent passwd someuser | cut -f6 -d:

getent peut faire beaucoup plus … voir la page de manuel . La firebase database passwd nsswitch renvoie l’entrée de l’utilisateur au format /etc/passwd . Il suffit de le diviser sur les deux points : pour parsingr les champs.

Il doit être installé sur la plupart des systèmes Linux (ou sur tout système utilisant GNU Lib C (RHEL: glibc-common , Deb: libc-bin )

Vous voulez l’option -u pour sudo dans ce cas. De la page de manuel:

 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, vous pouvez accéder à leur répertoire personnel avec ~ . Comme dans, pour aller dans mon répertoire personnel, vous utiliseriez cd ~chooban .

Donc, vous voulez:

  1. exécuter une partie d’un script bash en tant qu’utilisateur différent
  2. changer 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 ce qui suit:

 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. Pas sûr comment il se comporte dans d’autres * nixes.

  getent passwd "${OTHER_USER}"|cut -d\: -f 6 

Je cherchais aussi ceci, 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, ce serait /home/username

Suppose: Vous avez précédemment défini $username avec la valeur du nom d’utilisateur de l’utilisateur prévu. 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"))" 

Je me débattais 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 devait être exécuté en tant que root, rendant ainsi les solutions invoquer eval ou bash -c dangereux car ils ont permis l’injection de code dans la variable spécifiant le nom d’utilisateur.

Voici ce que j’ai trouvé. C’est simple et ne place pas de variable dans un sous-shell. Cependant, il faut que le script soit exécuté par root comme sudos dans le compte 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 renverra une erreur.

Voici une petite fonction shell qui n’ignore 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'"