Ubuntu – How to find who is logged-in as root

bash

Recently, I have asked "How do I list logged-in users?" The command who serves well for this purpose. But how do I find who is logged-in as root? Will the username "root" be?

Best Answer

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:

Related Question