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 -
.
Respuestas:
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 am i
es lo mismo que who smells bad
. Además, solo funciona si STDIN
está asociado con un TTY. Entonces, si lo ejecuta echo "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 que who am i
no funciona porque hay algún tipo de problema con el stdin no legible, en cuyo caso puede intentar canalizar los datos who 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, donde who 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
e who -m
implementan un truco en el que verifican a qué terminal está conectado stdin
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 pts/0 2011-07-03 19:18 (1.2.3.4)
joe pts/1 2011-07-03 19:10 (5.6.7.8)
tom
utilizado su
para llegar a la raíz y ejecuta su programa. Si STDIN
no se redirige, se logname
generará un programa como tom
. Si ES redirigido (por ejemplo, desde un archivo) así:
logname < /some/file
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 corriendo
logname < /dev/pts1
Ahora, 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.
Esta es una ksh
función que escribí en HP-UX. No sé cómo funcionará Bash
en Linux. La idea es que el sudo
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.
¿Qué tal usar logname (1) para obtener el nombre de inicio de sesión del usuario?
logname(1)
no funciona pero logname
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í.
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"
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
o who am i
no me dio la respuesta deseada, especialmente no en listas más largas de su 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.
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
y head
.
limitación: el comando no puede contener llaves ()
(normalmente no lo hace)
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
who | awk '{print $1}'