Lors de l'exécution d'un script via sudo ou su, je veux obtenir l'utilisateur d'origine. Cela devrait se produire indépendamment de plusieurs sudo
ou su
s'exécute à l'intérieur de l'autre et spécifiquement sudo su -
.
Réponses:
Résultats:
Utilisez who am i | awk '{print $1}'
OR logname
car aucune autre méthode n'est garantie.
Connecté en tant que soi:
evan> echo $USER
evan
evan> echo $SUDO_USER
evan> echo $LOGNAME
evan
evan> whoami
evan
evan> who am i | awk '{print $1}'
evan
evan> logname
evan
evan>
Sudo normal:
evan> sudo -s
root> echo $USER
root
root> echo $SUDO_USER
evan
root> echo $LOGNAME
root
root> whoami
root
root> who am i | awk '{print $1}'
evan
root> logname
evan
root>
sudo su -:
evan> sudo su -
[root ]# echo $USER
root
[root ]# echo $SUDO_USER
[root ]# echo $LOGNAME
root
[root ]# whoami
root
[root ]# who am i | awk '{print $1}'
evan
[root ]# logname
evan
[root ]#
sudo su -; su tom:
evan> sudo su -
[root ]# su tom
tom$ echo $USER
tom
tom$ echo $SUDO_USER
tom$ echo $LOGNAME
tom
tom$ whoami
tom
tom$ who am i | awk '{print $1}'
evan
tom$ logname
evan
tom$
who am i
est le même que who smells bad
. De plus, cela ne fonctionne que s'il STDIN
est associé à un TTY. Donc, si vous l'exécutez, echo "hello" | who am i
cela ne fonctionnera tout simplement pas.
echo "hello" | who am i
normalement, sauf si votre script s'exécute dans un environnement où il n'y a pas de terminal. Ensuite, vous pourriez voir l'erreur qui who am i
ne fonctionne pas car il y a une sorte de problème avec le stdin non lisible, auquel cas vous pouvez essayer de canaliser les données who am i
par désespoir pour satisfaire ses exigences stdin. tylerl fait juste remarquer qu'il a déjà emprunté cette voie et que le tube ne fonctionnera pas car stdin doit être à la fois lisible et associé à un TTY.
logname
maintenant, ce qui en fait fonctionne, où who am i
ne le fait pas.
Il n'y a pas de parfait réponse . Lorsque vous modifiez les ID utilisateur, l'ID utilisateur d'origine n'est généralement pas conservé et les informations sont donc perdues. Certains programmes, tels que logname
et who -m
implémentent un hack où ils vérifient à quel terminal est connecté stdin
, puis vérifient quel utilisateur est connecté sur ce terminal.
Cette solution souvent fonctionne , mais n'est pas infaillible et ne devrait certainement pas être considérée comme sûre. Par exemple, imaginez si who
génère ce qui suit:
tom pts/0 2011-07-03 19:18 (1.2.3.4)
joe pts/1 2011-07-03 19:10 (5.6.7.8)
tom
utilisé su
pour accéder à la racine et exécute votre programme. S'il STDIN
n'est pas redirigé, un programme comme celui-ci logname
sortiratom
. S'il est redirigé (par exemple à partir d'un fichier) comme suit:
logname < /some/file
Alors le résultat est "no login name
", puisque l'entrée n'est pas le terminal. Plus intéressant encore, cependant, est le fait que l'utilisateur peut se faire passer pour un autre utilisateur connecté. Puisque Joe est connecté sur pts / 1, Tom pourrait se faire passer pour lui en exécutant
logname < /dev/pts1
Maintenant, il dit joe
même si c'est Tom qui a exécuté la commande. En d'autres termes, si vous utilisez ce mécanisme dans n'importe quel rôle de sécurité, vous êtes fou.
C'est une ksh
fonction que j'ai écrite sur HP-UX. Je ne sais pas comment cela fonctionnera Bash
sous Linux. L'idée est que le sudo
processus s'exécute en tant qu'utilisateur d'origine et que les processus enfants sont l'utilisateur cible. En parcourant les processus parents, nous pouvons trouver l'utilisateur du processus d'origine.
#
# The options of ps require UNIX_STD=2003. I am setting it
# in a subshell to avoid having it pollute the parent's namespace.
#
function findUser
{
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
( export UNIX_STD=2003; ps -p$thisPID -ouser,ppid,pid,comm ) | grep $thisPID | read thisUser myPPid myPid myComm
thisPID=$myPPid
done
if [ "$thisUser" = "root" ]
then
thisUser=$origUser
fi
if [ "$#" -gt "0" ]
then
echo $origUser--$thisUser--$myComm
else
echo $thisUser
fi
return 0
}
Je sais que la question originale remonte à il y a longtemps, mais des gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution.
Que diriez-vous d'utiliser logname (1) pour obtenir le nom de connexion de l'utilisateur?
logname(1)
ne fonctionne pas mais logname
fait - en ajoutant les résultats ci
$LOGNAME
mais cela n'a pas fonctionné. Également ajouté aux résultats ci-dessus.
logname
toujours un tty? Avec mes tests, ça passe toujours. (Peut-être que j'ai quelque chose de mal.) J'utilise Linux avec coreutils 8.26.
THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
C'est la seule chose qui a fonctionné pour moi.
La fonction findUser () de user1683793 est portée bash
et étendue pour qu'elle renvoie également les noms d'utilisateurs stockés dans les bibliothèques NSS.
#!/bin/bash
function findUser() {
thisPID=$$
origUser=$(whoami)
thisUser=$origUser
while [ "$thisUser" = "$origUser" ]
do
ARR=($(ps h -p$thisPID -ouser,ppid;))
thisUser="${ARR[0]}"
myPPid="${ARR[1]}"
thisPID=$myPPid
done
getent passwd "$thisUser" | cut -d: -f1
}
user=$(findUser)
echo "logged in: $user"
revenir en arrière et donner une liste d'utilisateurs
basé sur la réponse de user1683793
En excluant les processus non-TTY, j'ignore root en tant qu'initiateur de la connexion. Je ne suis pas sûr que cela puisse en exclure trop dans certains cas
#!/bin/ksh
function findUserList
{
typeset userList prevUser thisPID thisUser myPPid myPid myTTY myComm
thisPID=$$ # starting with this process-ID
while [ "$thisPID" != 1 ] # and cycling back to the origin
do
( ps -p$thisPID -ouser,ppid,pid,tty,comm ) | grep $thisPID | read thisUser myPPid myPid myTTY myComm
thisPID=$myPPid
[[ $myComm =~ ^su ]] && continue # su is always run by root -> skip it
[[ $myTTY == '?' ]] && continue # skip what is running somewhere in the background (without a terminal)
if [[ $prevUser != $thisUser ]]; then # we only want the change of user
prevUser="$thisUser" # keep the user for comparing
userList="${userList:+$userList }$thisUser" # and add the new user to the list
fi
#print "$thisPID=$thisUser: $userList -> $thisUser -> $myComm " >&2
done
print "$userList"
return 0
}
logname
ou who am i
ne me donne pas la réponse souhaitée, surtout pas dans les listes plus longues su user1
, su user2
, su user3
,...
Je sais que la question originale remonte à il y a longtemps, mais des gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution.
Alternative à l'appel ps plusieurs fois: faites un appel pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
sortie (une fois connecté comme pair): (evan)
arguments pstree:
Obtenez le premier changement d'utilisateur (qui est la connexion) avec grep -o
ethead
.
limitation: la commande peut ne pas contenir d'accolades ()
(elle ne le fait normalement pas)
Sur les systèmes en cours d'exécution systemd-logind
, l' API systemd fournit ces informations . Si vous souhaitez accéder à ces informations à partir d'un script shell, vous devez utiliser quelque chose comme ceci:
$ loginctl session-status \
| (read session_id ignored; loginctl show-session -p User $session_id)
User=1000
Les commandes système session-status
et show-ssession
de loginctl
ont un comportement différent sans arguments: session-status
utilise la session en cours, mais show-ssession
utilise le gestionnaire. Cependant, l'utilisation show-session
est préférable pour l'utilisation de scripts en raison de sa sortie lisible par machine. C'est pourquoi deux invocations de loginctl
sont nécessaires.
who | awk '{print $1}'