Lors de l'exécution d'un script via Sudo ou su, je souhaite obtenir l'utilisateur d'origine. Cela devrait se produire quelles que soient les exécutions Sudo
ou su
et notamment Sudo su -
.
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$
Il n'y a pas de réponse parfaite. Lorsque vous modifiez les ID utilisateur, l'ID utilisateur d'origine n'est généralement pas conservé. 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 déterminent quel utilisateur est connecté à ce terminal.
Cette solution souvent fonctionne, mais n’est pas infaillible et ne devrait certainement pas être considérée comme sécurisée. Par exemple, imaginez si who
génère les éléments suivants:
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
a utilisé su
pour aller à la racine et exécute votre programme. Si STDIN
n'est pas redirigé, un programme comme logname
affichera tom
. Si IS 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. Ce qui est encore plus intéressant, c’est que l’utilisateur puisse se faire passer pour un autre utilisateur connecté. Depuis que Joe est connecté sur pts/1, Tom pourrait se faire passer pour lui en courant
logname < /dev/pts1
Maintenant, il est écrit joe
même si tom est celui 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 fonction ksh
que j’ai écrite sur HP-UX. Je ne sais pas comment cela fonctionnera avec Bash
sous Linux. L'idée est que le processus Sudo
est exécuté en tant qu'utilisateur d'origine et que les processus enfants sont l'utilisateur cible. En revenant en arrière dans 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 initiale remontait à il y a longtemps, mais les gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution en place.
Pourquoi ne pas utiliser logname (1) pour obtenir le nom de connexion de l'utilisateur?
la fonction findUser () de user1683793 a été portée à bash
et étendue afin de renvoyer les noms d'utilisateur 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 et donner une liste des utilisateurs
basé sur la réponse de user1683793
En excluant les processus non-TTY, je saute root en tant qu'initiateur de la connexion. Je ne sais pas si cela peut en excéder 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 m'a pas donné la réponse souhaitée, surtout pas dans les listes plus longues de su user1
, su user2
, su user3
, ...
Je sais que la question initiale remontait à il y a longtemps, mais les gens (comme moi) le demandent toujours et cela semblait être un bon endroit pour mettre la solution en place.
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.
Alternative à appeler ps plusieurs fois: faire un appel pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
sortie (lorsque connecté en tant que pair): (evan)
pstree arguments:
Obtenez le premier changement d'utilisateur (qui est login) avec grep -o
et head
.
limitation: la commande ne doit contenir aucune accolade ()
(normalement pas)