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
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:
sudoers
peuvent emprunter l’identité d’autres utilisateurs via sudo
. 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:
-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
. 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:
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) someUser
de someUser
de someUser
. -s
crée un shell non connecté:
~/.bashrc
) -H
, le processus d’emprunt d’identité signalera le répertoire de base de l’ utilisateur d’origine dans $HOME
. L’utilisation d’un shell signifie que les arguments de chaîne transmis sur la ligne de commande PEUVENT être soumis à des extensions de shell – voir 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 plate – forme 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
…
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:
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'"