Al ejecutar un script a través de sudo o su, quiero obtener el usuario original. Esto debería suceder independientemente de que se ejecuten múltiples sudo
o su
uno dentro del otro y específicamente sudo su -
.
93
Resultados:
Utilice who am i | awk '{print $1}'
OR logname
ya que no se garantizan otros métodos.
Iniciar sesión como yo:
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 | awk '{print $1}'
who am i
es lo mismo quewho smells bad
. Además, solo funciona siSTDIN
está asociado con un TTY. Entonces, si lo ejecutaecho "hello" | who am i
, simplemente no funcionará.echo "hello" | who am i
normalmente, a menos que su script se esté ejecutando en un entorno donde no hay una terminal. Luego, es posible que vea el error quewho am i
no funciona porque hay algún tipo de problema con el stdin no legible, en cuyo caso puede intentar canalizar los datoswho am i
por desesperación para satisfacer su requisito de stdin. tylerl solo está notando que ya ha recorrido ese camino, y la tubería no funcionará porque stdin debe ser legible y estar asociado con un TTY.logname
ahora, que resulta que funciona, dondewho am i
no.No hay una respuesta perfecta . Cuando cambia las ID de usuario, la ID de usuario original no suele conservarse, por lo que se pierde la información. Algunos programas, como
logname
ewho -m
implementan un truco en el que verifican a qué terminal está conectadostdin
y luego verifican qué usuario ha iniciado sesión en ese terminal.Esta solución a menudo funciona, pero no es infalible y ciertamente no debe considerarse segura. Por ejemplo, imagina si
who
genera lo siguiente:tom
utilizadosu
para llegar a la raíz y ejecuta su programa. SiSTDIN
no se redirige, selogname
generará un programa comotom
. Si ES redirigido (por ejemplo, desde un archivo) así:Entonces el resultado es "
no login name
", ya que la entrada no es el terminal. Más interesante aún, sin embargo, es el hecho de que el usuario podría hacerse pasar por un usuario que inició sesión diferente. Dado que Joe está conectado en pts / 1, Tom podría fingir ser él corriendoAhora, dice
joe
a pesar de que Tom es quien ejecutó el comando. En otras palabras, si utiliza este mecanismo en cualquier tipo de función de seguridad, está loco.fuente
Esta es una
ksh
función que escribí en HP-UX. No sé cómo funcionaráBash
en Linux. La idea es que elsudo
proceso se esté ejecutando como el usuario original y los procesos secundarios sean el usuario objetivo. Al retroceder por los procesos principales, podemos encontrar al usuario del proceso original.# # 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 }
Sé que la pregunta original era de hace mucho tiempo, pero la gente (como yo) todavía está preguntando y este parecía un buen lugar para poner la solución.
fuente
¿Qué tal usar logname (1) para obtener el nombre de inicio de sesión del usuario?
fuente
logname(1)
no funciona perologname
sí - agregando los resultados anteriores$LOGNAME
pero no funcionó. También se agregó a los resultados anteriores.logname
Todavía requiere un tty? Con mis pruebas siempre pasa. (Tal vez me haya equivocado de algo.) Estoy ejecutando linux con coreutils 8.26.THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Eso es lo único que funcionó para mí.
fuente
La función findUser () de user1683793 se transfirió
bash
y extendió para que también devuelva los nombres de usuario almacenados en las bibliotecas 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"
fuente
retroceder y dar una lista de usuarios
basado en la respuesta del usuario1683793
Al excluir los procesos que no son TTY, omito root como iniciador del inicio de sesión. No estoy seguro de si eso puede excluir demasiado en algún caso
#!/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
owho am i
no me dio la respuesta deseada, especialmente no en listas más largas desu user1
,su user2
,su user3
,...
Sé que la pregunta original era de hace mucho tiempo, pero la gente (como yo) todavía está preguntando y este parecía un buen lugar para poner la solución.
fuente
Alternativa a llamar a ps varias veces: haga una llamada pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
salida (cuando se inicia sesión como par):
(evan)
pstree argumentos:
Obtenga el primer cambio de usuario (que es inicio de sesión) con
grep -o
yhead
.limitación: el comando no puede contener llaves
()
(normalmente no lo hace)fuente
En los sistemas en ejecución
systemd-logind
, la API systemd proporciona esta información . Si desea acceder a esta información desde un script de shell, debe usar algo como esto:$ loginctl session-status \ | (read session_id ignored; loginctl show-session -p User $session_id) User=1000
Los comandos del sistema
session-status
y tienen un comportamiento diferente sin argumentos: usa la sesión actual, pero usa el administrador. Sin embargo, es preferible utilizar scripts debido a su salida legible por máquina. Es por eso que se necesitan dos invocaciones de .show-ssession
loginctl
session-status
show-ssession
show-session
loginctl
fuente