Eu assumo que a conta raiz não está habilitada (como é por padrão), então somente sudo -i
é aplicável para um usuário se tornar root . Minha sugestão é o seguinte script que usa os comandos who -u
e pgrep -at <tty parsed from who -u>
para descobrir qual user
na qual tty
executou o comando sudo -i
.
#!/bin/bash
LANG=C who -u | while read -a line; do # Output the whole line: echo "${line[@]}"
IS_ROOT="$(pgrep -at "${line[1]}" | grep 'sudo -i')"
[[ ! -z "${IS_ROOT}" ]] && printf '%-7s ( PID %-6s at %s on TTY %-7s) is ROOT: %s %s\n' "${line[0]}" "${line[5]}" "${line[4]}" "${line[1]}" "$IS_ROOT"
done | sed '/grep sudo -i/d' | sort -k13 -k6
Explicação:
-
who -u
mostra os usuários conectados com os PIDs de suas sessões. ProvavelmenteLANG=C
não é obrigatório - ele é colocado para garantir formato de data / hora idêntico em máquinas com diferentes configurações delocale
. -
O loop
while
irádo
dos comandos enquanto houver fluxo no stdin . -
O comando
read -a
lerá o fluxo de entrada linha por linha e atribuirá essas linhas como uma matriz à "variável"$line
. Nós poderíamos produzir toda a linha por um comando como:echo "${line[@]}"
. Portanto,${line[1]}
significa a segunda variável da matriz$line
(a primeira é0
). No caso atual,${line[1]}
é o TTY da saída dewho -u
. -
Aqui está um script simples que gerará uma "tabela" com as relações entre os elementos da matriz e seus valores:
line=( $(LANG=C who -u | head -1) ); for i in {0..6}; do printf '%-11s' "${line[$i]}"; done; echo; for i in {0..6}; do printf '${line[%s]} ' "$i"; done; echo guest tty7 2018-01-03 09:52 old 1847 (:0) ${line[0]} ${line[1]} ${line[2]} ${line[3]} ${line[4]} ${line[5]} ${line[6]}
-
A saída do comando
pgrep -at "${line[1]}" | grep 'sudo -i'
será assinada como valor$()
para a variável$IS_ROOT
. -
O comando
pgrep -at "TTY"
produzirá os PIDs de todos os processos em determinados TTY - opção-t
--terminal
, e a opção-a
--list-name
listará os nomes de PIDs e processos. -
A expressão
[[ ! -z "${IS_ROOT}" ]] &&
pode ser lida desta forma: se[
a variável"${IS_ROOT}"
não for!
vazio-z
, então&&
ou senão||
. -
O comando
printf
é usado para formatar a saída ( referência ):printf '%s some text %s' "$var1" "$var2"
-
Finalmente,
sed '/grep sudo -i/d'
excluirá a linha não assistida (que contém nosso comandogrep 'sudo -i'
) da saída dewhile
esort -k13 -k6
classificará a saída pelas colunas 13 e 6.
Chame o script find-root
, torne-o executável ( chmod +x find-root
) e execute-o.
Aqui está uma saída simples:
$ ./find-root
spas ( PID 14035 at 12:54 on TTY pts/20 ) is ROOT: 23518 sudo -i
spas ( PID 14035 at 12:36 on TTY pts/4 ) is ROOT: 23589 sudo -i
guest ( PID 23575 at 15:00 on TTY pts/4 ) is ROOT: 23589 sudo -i
guest ( PID 24321 at 15:30 on TTY tty1 ) is ROOT: 24386 sudo -i
Aqui está uma demonstração (em uma sessão mutt
) de como o script funciona ( em sua versão anterior ):
Coloque o script em /usr/local/bin
para disponibilizá-lo como comando shell. Para fazer isso, copie e execute as seguintes linhas como um único comando:
cat << EOF | sudo tee /usr/local/bin/find-root && sudo chmod +x /usr/local/bin/find-root
#!/bin/bash
LANG=C who -u | while read -a line; do
IS_ROOT="$(pgrep -at "${line[1]}" | grep 'sudo -i')"
[[ ! -z "${IS_ROOT}" ]] && printf '%-7s ( PID %-6s at %s on TTY %-7s) is ROOT: %s %s\n' "${line[0]}" "${line[5]}" "${line[4]}" "${line[1]}" "$IS_ROOT"
done | sed '/grep sudo -i/d' | sort -k13 -k6
EOF
Explicação:
-
O comando
cat << EOF
produzirá as próximas linhas, a menos que a stringEOF
seja encontrada. Observe as barras invertidas$
que irão escapar do caractere especial$
e serão produzidas literalmente dentro de cat. -
Esta saída será canalizada
|
para o stdin do comandotee
(executado porsudo
) que gravará o arquivo/usr/local/bin/find-root
. -
Se o comando anterior for bem-sucedido
&&
, o comandosuddo chmod +x
será executado.
Veja também: