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?
4 Answers
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 -ushows the users logged on with the PIDs of their sessions. ProbablyLANG=Cis not mandatory - it is placed to guarantee identical time/date format on machines with differentlocale's settings.The loop
whilewilldothe commands while there is stream on the stdin.The command
read -awill 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 is0). In the current case${line[1]}is the TTY from the output ofwho -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-namewill 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-zthen&&or else||.The
printfcommand 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 commandgrep 'sudo -i') from the output ofwhileandsort -k13 -k6will 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):
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 << EOFwill output the next lines unless the stringEOFis 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 commandtee(executed bysudo) that will write the file/usr/local/bin/find-root.If the previous command is successful
&&the commandsuddo chmod +xwill be executed.
See also:
- 29,351
- 10
- 85
- 161
-
1Since you're using bash, you could take advantage of `read -a` to assign to array and avoid using awk for parsing, or just assign tons of variables with `read` . Just suggestion. Nice script – Sergiy Kolodyazhnyy Nov 28 '17 at 18:15
-
Thank you for the advice @SergiyKolodyazhnyy! I've rewrote the answer. – pa4080 Nov 29 '17 at 10:26
-
@pa3080 Awesome :) Looks pretty good – Sergiy Kolodyazhnyy Nov 29 '17 at 10:33
-
Note that there are other ways of elevating to root than just "sudo -i" - "sudo bash" and "sudo su -" will also give you a root shell, and I'm not sure if this script will catch it. – ArrayBolt3 May 29 '22 at 22:57
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.
- 103,293
- 19
- 273
- 492
-
1Odd thing, if you use `screen` while being `sudo su` and create a couple of windows in it, they will be all logged in `who` and `w` as being `root`instead of username --> https://i.stack.imgur.com/iz2zs.png – Videonauth Nov 29 '17 at 02:07
-
@videonauth that probably also depends on whether or not terminal registered with `utmp` login database, which screen does. I had problems with `wall` in gnome-terminal because `gnome-terminal ` doesn't register with utmp. Even have a question about it posted. – Sergiy Kolodyazhnyy Nov 29 '17 at 02:12
Usually in Ubuntu, the SuperUser or Root account is named root but is locked by the system and you cannot login into it. To answer your question, yes, the username would be root although you can not use it without unlocking it.
To unlock it type the following into a terminal:
sudo -i
Then Set a password for root:
sudo passwd root
More information on this can be found here:
- 623
- 1
- 5
- 19
-
-
@Anony by using sudo in the terminal or typing sudo su to root the terminal – Max Nov 30 '17 at 01:56
-
@Anony, or by using sudo -i and then sudo passwd root to set the custom password for root. – Max Nov 30 '17 at 02:10
Type this
sudo less /var/log/auth.log
from there you can be able to browse all logins including those who access root
- 224
- 1
- 6
-
thanks.But its showing : Sorry, user "username" is not allowed to execute '/usr/bin/less /var/log/auth.log' as root on "servername". – Anony Nov 28 '17 at 07:28
-
make sure the username you have, have root privileges or belong in the sudo group then after that you can be able to view it – Yien Nov 28 '17 at 07:35
-
-
without any sudo privileges you can't as most of the log files belong to a group that requires superuser privileges, unless of course you modified it not to. However, based on your questions here it is only limited to and asking another one would be adviseable. Choose an answer here which you found one that suits you and ask another question. – Yien Nov 28 '17 at 10:00
