Ao executar um script via sudo ou su, desejo obter o usuário original. Isso deve acontecer independentemente de múltiplas sudo
ou su
execuções dentro umas das outras e especificamente sudo su -
.
93
Resultados:
Use who am i | awk '{print $1}'
OR, logname
pois nenhum outro método é garantido.
Conectado como eu:
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
é o mesmo quewho smells bad
. Além disso, só funciona seSTDIN
estiver associado a um TTY. Portanto, se você executá-echo "hello" | who am i
lo, simplesmente não funcionará.echo "hello" | who am i
normalmente, a menos que seu script estivesse sendo executado em um ambiente onde não houvesse terminal. Em seguida, você pode ver o erro quewho am i
não está funcionando porque há algum tipo de problema com o stdin não legível, caso em que você pode tentar canalizar os dados parawho am i
, desesperado, para satisfazer seu requisito stdin. tylerl está apenas observando que já percorreu esse caminho e o pipe não funcionará porque stdin deve ser legível e associado a um TTY.logname
agora, o que parece funcionar, ondewho am i
não funciona.Não existe uma resposta perfeita . Quando você altera os IDs do usuário, o ID do usuário original geralmente não é preservado, portanto as informações são perdidas. Alguns programas, como
logname
ewho -m
implementam um hack onde verificam para ver qual terminal está conectadostdin
, e então ver qual usuário está logado naquele terminal.Essa solução geralmente funciona, mas não é infalível e certamente não deve ser considerada segura. Por exemplo, imagine se a
who
saída for o seguinte:tom
usadosu
para fazer root e executa seu programa. SeSTDIN
não for redirecionado, um programa semelhantelogname
será geradotom
. Se for redirecionado (por exemplo, de um arquivo) da seguinte forma:Então o resultado é "
no login name
", já que a entrada não é o terminal. Mais interessante ainda, porém, é o fato de que o usuário pode se passar por um usuário logado diferente. Como Joe está conectado em pts / 1, Tom poderia fingir ser ele executandoAgora, ele diz
joe
mesmo que Tom é quem executou o comando. Em outras palavras, se você usar esse mecanismo em qualquer tipo de função de segurança, você ficará louco.fonte
Esta é uma
ksh
função que escrevi no HP-UX. Não sei como vai funcionarBash
no Linux. A ideia é que osudo
processo esteja sendo executado como o usuário original e os processos filhos sejam o usuário-alvo. Percorrendo os processos pais, podemos encontrar o usuário do processo 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 }
Sei que a pergunta original era de muito tempo atrás, mas as pessoas (como eu) ainda estão perguntando e este parecia um bom lugar para colocar a solução.
fonte
Que tal usar logname (1) para obter o nome de login do usuário?
fonte
logname(1)
não funciona, maslogname
funciona - adicionando os resultados acima$LOGNAME
mas não funcionou. Também adicionado aos resultados acima.logname
ainda necessitam de um tty? Com meus testes sempre passa. (Talvez eu tenha algo errado.) Estou executando o Linux com coreutils 8.26.THIS_USER=`pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1 | sed 's/[()]//g'`
Essa é a única coisa que funcionou para mim.
fonte
A função findUser () do user1683793 foi transferida
bash
e estendida para que também retorne nomes de usuários armazenados nas 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"
fonte
voltando e dando uma lista de usuários
com base na resposta do usuário1683793
Ao excluir os processos não-TTY, pulo o root como o iniciador do login. Não tenho certeza se isso pode significar muito em alguns casos
#!/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
ouwho am i
não me dar a resposta desejada, especialmente não em listas mais longas desu user1
,su user2
,su user3
,...
Sei que a pergunta original era de muito tempo atrás, mas as pessoas (como eu) ainda estão perguntando e este parecia um bom lugar para colocar a solução.
fonte
Alternativa para chamar ps várias vezes: faça uma chamada pstree
pstree -lu -s $$ | grep --max-count=1 -o '([^)]*)' | head -n 1
saída (quando conectado como par):
(evan)
argumentos pstree:
Obtenha a primeira alteração do usuário (que é o login) com
grep -o
ehead
.limitação: o comando não pode conter chaves
()
(normalmente não contém )fonte
Em sistemas em execução
systemd-logind
, a API systemd fornece essas informações . Se quiser acessar essas informações a partir de um script de shell, use algo como este:$ loginctl session-status \ | (read session_id ignored; loginctl show-session -p User $session_id) User=1000
Os comandos do sistema
session-status
e têm comportamentos diferentes sem argumentos: usa a sessão atual, mas usa o gerenciador. No entanto, o uso é preferível para uso de script devido à sua saída legível por máquina. É por isso que duas invocações de são necessárias.show-ssession
loginctl
session-status
show-ssession
show-session
loginctl
fonte