129

If I create the script /root/bin/whoami.sh containing:

#!/bin/bash
whoami

and this script is called by a user with a properly configured sudo, it will indicate

root

Is there a fast way to obtain the actual user in a script, or will I have to resort to parameters passing along this username?

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
quadmore
  • 1,291
  • 2
  • 8
  • 3

8 Answers8

168

$SUDO_USER doesn't work if you are using sudo su -.
It also requires multiple checks - if $USER == 'root' then get $SUDO_USER.

Instead of the command whoami use who am i. This runs the who command filtered for the current session. It gives you more info than you need. So, do this to get just the user:

who am i | awk '{print $1}'

Alternatively (and simpler) you can use logname. It does the same thing as the above statement.

This gives you the username that logged in to the session.

These work regardless of sudo or sudo su [whatever]. It also works regardless of how many times su and sudo are called.

evan
  • 12,307
  • 7
  • 37
  • 51
  • 57
    Alternative to `who am i` is `who mom likes`. Your choice. – wchargin Aug 31 '14 at 20:36
  • 3
    `who` returns 2 lines for me, both containing my name, and `who am i` returns none. Any help? – GManz Sep 23 '14 at 20:55
  • I notice that this doesn't work in a docker container, as the `who am i` seems to depend on login and thus returns blank. Try `docker run -it ubuntu bash`, and `whoami` gives the user (root in this case, but works correctly with alternate users), while `who am i` is blank. – cboettig Jan 05 '15 at 20:42
  • Thanks, I'm using `owner() { ls -ld $1 | awk '{print $3}'; }` in my script to get the owner string; usage: `if [ "$(owner $file)" != $(logname) ]` – AVProgrammer Dec 03 '15 at 17:49
  • 10
    I'm on Ubuntu 16.04 and the command `who am i` does nothing, it seems to be simply `who`, so `who | awk '{print $1}'` works as expected ;) – daveoncode May 15 '16 at 08:43
  • 3
    Just incase you don't have `awk` installed, you can also use `cut`: `who mom likes | cut -d' ' -f1` or `sed` for some reason: `who mom likes | sed -n 's/^\([^ ]*\).*/\1/p'` – Yzmir Ramirez Aug 02 '16 at 17:05
  • I have question. If I have the following script : `1 #~/bin/bash 2 3 USERNAME=`who am i` 4 5 echo "$USERNAME" ` ~ and if I execute `sed -n 5p ./second.sh | sudo bash` and on the terminal "root" is printed instead of the user with whom I execute this command? – DPM Dec 30 '16 at 11:47
  • 1
    Note: `logname` doesn't work when you run it from a terminal window because it's a non-login terminal. – Lucas Jun 13 '17 at 17:01
  • Interestingly `who` returns my graphical and numerous (tmux) sessions, while `who am i` returns only the current session where I am running the command. This could get interesting where you might need a `head -1` or to try `who am i` if you see more than $# = 1 lines in the first return. If I run a script as another user that has sudo permissions to a specific path that is NOT my primary login user (say a service account that needs to run eg nginx with sudo to grab port 80) I'm not sure what it will return. – dragon788 Nov 17 '17 at 15:38
  • @daveoncode: your approach works if your current user was the first to log in... https://stackoverflow.com/a/14429361/1587329 seems to work in all cases – serv-inc Nov 08 '18 at 10:20
66

I think $SUDO_USER is valid.

#!/bin/bash
echo $SUDO_USER
whoami
Bit-Man
  • 516
  • 4
  • 17
Brandon Horsley
  • 7,956
  • 1
  • 29
  • 28
  • 3
    Strange thing: `sudo env` shows `SUDO_USER` but `sudo echo $SUDO_USER` prints nothing... – mtvec Aug 19 '10 at 13:54
  • 20
    job, this is not strange, it's expected. in `sudo echo $SUDO_USER`, bash is evaluating $SUDO_USER **before** executing sudo. try the script posted in this solution, it works. –  Aug 19 '10 at 13:57
  • @quadmore: If you're happy with the answer, don't forget to accept it. – mtvec Aug 19 '10 at 14:41
  • 4
    You could also use `echo ${SUDO_USER:-$USER}` to catch both `sudo` and non-sudo running. But [evan's answer](http://stackoverflow.com/a/4597929/321973) `logname` sounds easer – Tobias Kienzler Feb 06 '13 at 09:34
  • 2
    @TobiasKienzler - And as evan points out, `$SUDO_USER` doesn't work with `sudo su -`, but `logname` always works. – David Harkness Sep 06 '13 at 18:42
  • sudo sh -c "echo \$SUDO_USER" – Boopathi Rajaa Nov 29 '13 at 11:14
15

Here is how to get the username of the person who called the script no matter if sudo or not:

if [ $SUDO_USER ]; then user=$SUDO_USER; else user=`whoami`; fi

or a shorter version

[ $SUDO_USER ] && user=$SUDO_USER || user=`whoami`
Alexei Tenitski
  • 9,030
  • 6
  • 41
  • 50
8

Using whoami, who am i, who, id or $SUDO_USER isn't right here.

Actually, who is never a solution to the question, as it will only list the logged in users, which might be dozens...

In my eyes, the only valuable answer is the use of logname.

Hope this helps

Rob

Rob
  • 81
  • 1
  • 1
5

If it's the UID you're looking for (useful for docker shenanigans), then this works:

LOCAL_USER_ID=$(id -u $(logname))
Jim Hunziker
  • 14,111
  • 8
  • 58
  • 64
2

who am i | awk '{print $1}' didn't work for me but who|awk '{print $1}' will serve the job

Srinivas
  • 147
  • 3
  • 15
  • 2
    Not on a host where more than one user has session – Roman Grazhdan Dec 17 '18 at 15:14
  • It's `whoami` all one word, not `who am i`. This follows typical structure where shell commands typically are a single word, with arguments following. `who am i` would be interpereted as running the command `who` with the arguments of `am` and `i`. `who` just so happens to also be a command, but it outputs more than is needed in this case, whereas `whoami` just prints the username. – Eli Smith Nov 09 '22 at 23:32
1

Odd, the system does distinguish between real and effective UIDs, but I can find no program that exports this at shell level.

msw
  • 42,753
  • 9
  • 87
  • 112
0

Having the same question, using Rocky Linux 9.2, I ran this script:

#!/bin/bash
echo "LOGNAME: $LOGNAME"
echo "SUDO_USER: $SUDO_USER"
set | grep username

in each of these scenarios:

  • as user (./script.sh)

    • LOGNAME: username
    • SUDO_USER: null
  • as root via sudo (sudo ./script.sh)

    • LOGNAME: root
    • SUDO_USER: username
  • as root via su (./script.sh)

    • LOGNAME: username
    • SUDO_USER: null
  • as root via sudo su (./script.sh)

    • LOGNAME: root
    • SUDO_USER: username

Using an if...then...else check would work, unless you inadvertently sudo run the script while you are already at the superuser prompt:

#root: sudo ./script.sh
  • via either su or sudo su the results are
    • LOGNAME: root
    • SUDO_USER: root

However, one set variable has proven to be consistent though all of my scenarios:

MAIL=/var/spool/mail/username

I now set the logged in user as:

UNAME=$(echo $MAIL |cut -d/ -f5)

I'm sure there are situations where this would not work, but I haven't found one yet.

B H
  • 111
  • 1
  • 3