How do I find who is logged-in as root?

I assume the root account is not enabled (as it is by default), so only sudo -i is applicable for a user to become root. My suggestion is the following script that uses the commands who -u and pgrep -at <tty parsed from who -u> to find which user on which tty have executed the command 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

Explanation:

  • who -u shows the users logged on with the PIDs of their sessions. Probably LANG=C is not mandatory - it is placed to guarantee identical time/date format on machines with different locale's settings.

  • The loop while will do the commands while there is stream on the stdin.

  • The command read -a will read the input stream line by line and will assign these lines as an array to the "variable" $line. We could output the whole line by a command as: echo "${line[@]}". So ${line[1]} means the second variable of the array $line (the first is 0). In the current case ${line[1]} is the TTY from the output of who -u.

  • Here is a simple script that will output a "table" with the relations betwen the array elements and their values:

    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]}
    
  • The output of the command pgrep -at "${line[1]}" | grep 'sudo -i' will be signed as value $() to the variable $IS_ROOT.

  • The command pgrep -at "TTY" will output the PIDs of all processes on certain TTY - option -t --terminal, and the option -a --list-name will list the PIDs and processes names.

  • The expression [[ ! -z "${IS_ROOT}" ]] && could be read in this way: if [ the variable "${IS_ROOT}" is not ! empty -z then && or else ||.

  • The printf command is used to format the output (reference):

    printf '%s some text %s` "$var1" "$var2"
    
  • Finally sed '/grep sudo -i/d' will delete the unattended line (that contains our command grep 'sudo -i') from the output of while and sort -k13 -k6 will sort the output by columns 13 and 6.


Call the script find-root, make it executable (chmod +x find-root) and execute it.

Here is a simple output:

$ ./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

Here is a demonstration (in a mutt session) how the script works (in its previous version):

enter image description here


Place the script in /usr/local/bin to make it available as shell command. To do that, copy and execute the following lines as single command:

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

Explanation:

  • The command cat << EOF will output the next lines unless the string EOF is encountered. Note the backslashes \$ that will escape the special character $ and it will be outputted literally within cat.

  • This output will be piped | to the stdin of the command tee (executed by sudo) that will write the file /usr/local/bin/find-root.

  • If the previous command is successful && the command suddo chmod +x will be executed.


See also:

  • How do I get the list of the active login sessions?

  • How do I list logged-in users without duplicates?

  • Why is it bad to log in as root?

  • How to enable root login?


On Ubuntu, logging into root account is disabled, however sudo users can still log in as root via sudo -i. However, neither who and w command on Ubuntu will show you being logged in as root:

$ sudo -i
[sudo] password for xieerqi: 
$ who
xieerqi  tty7         2017-11-27 23:39 (:0)
xieerqi  pts/14       2017-11-27 23:39 (:0)
xieerqi  pts/0        2017-11-28 00:25 (:0)

Here I am logged in on pts/14 via sudo -i, however my original username is still there. What can be done, however, is to filter process list to find the shell running on that terminal. Of course that process is going to be running as root.

$ ps -u root | awk '$2 ~ /pts/'                                                                
 4170 pts/14   00:00:00 sudo
 4172 pts/14   00:00:00 bash

That way, by cross referencing you can figure out who is logged in as root in terminal. Remember, that you also should include tty into awk command in case there are root users logged in on tty.

Another one, would be to filter /var/log/auth.log as suggested already in other answers:

awk '/USER=root/' /var/log/auth.log

However, this is a log file. It only displays who has logged in or failed to log in, not who's currently is at superuser level.