1. Overview

Sometimes, when we write a shell script, we want to know who is the current login user.

Usually, we can get the information by reading the $USER variable or calling the whoami command. However, this approach won’t work if the shell script is called with sudo.

In this tutorial, we’ll take a closer look at the problem. Further, we’ll address the technique of retrieving the login user in a shell script even if the user calls the script with the sudo command.

2. Introduction to the Problem

2.1. Understanding the Problem

Let’s understand the problem through a simple example:

$ cat ./get_user.sh
#!/bin/bash

echo "Get the current login user by reading the \$USER variable: "$USER
echo "Get the current login user by the whoami command: "$(whoami)

In the above script, we have a couple of echo commands. They print the current login user by the $USER environment variable and the command whoami.

If we log in as a regular user kent and call the script:

kent$ ./get_user.sh 
Get the current login user by reading the $USER variable: kent
Get the current login user by the whoami command: kent

As we expected, both echo commands print kent as the current login user. However, let’s see if it still works when we call the script with the sudo command:

kent$ sudo ./get_user.sh 
[sudo] password for kent: 
Get the current login user by reading the $USER variable: root
Get the current login user by the whoami command: root

This time, after we gave the password, we see both echo commands print root. Here, root is the effective user who executes the script. However, it’s not the login user. The current login user is kent. We’re looking for a way to identify the current login user in a shell script.

2.2. Why the who Command Is Not the Solution

When we talk about the login user, we may think of the convenient who command.

Let’s execute the who command and see what it prints:

kent$ who
kent     tty7         2021-06-30 22:58 (:0)

The who command can list users who are currently logged in. So, the user kent is listed. It seems that it was the exact answer we’re looking for.

In our script, we can parse the output of the who command and get the current login user. This idea may work for this example. However, it makes the script unstable.

Let’s review the who output. We have only one output line. This is because currently, only user kent has logged in to the system. However, Linux is a multi-user system. So now, let’s log in to the system by another user guest and launch the who command once again:

kent$ who
kent     tty7         2021-06-30 22:58 (:0)
guest    tty4         2021-07-04 20:26

As we can see, all logged-in users are listed by the who command. That is to say, once our script is executed by the sudo command, we cannot rely on the who command to distinguish which user executed the script.

This is also a common pitfall when we want to get the current login user. Next, let’s find out stable solutions to the problem.

3. Using the logname Command

logname is a member of the coreutils package. Therefore, it’s available on all Linux distros.

The logname command prints the user’s login name.

Let’s see if it can solve our problem. First, let’s write a new shell script:

$ cat by_logname.sh
#!/bin/bash

echo "The login user is "$(logname)

Next, let’s execute the shell script with and without sudo:

kent$ ./by_logname.sh
The login user is kent

kent$ sudo ./by_logname.sh
[sudo] password for kent: 
The login user is kent

As the output above shows, our script outputs kent on both cases. Therefore, the problem has been solved using the logname command.

4. Using the $SUDO_USER Variable

When we use the sudo command, the original login name of the user who invoked sudo will be stored in a variable $SUDO_USER.

Let’s create a small script to test it:

kent$ cat by_sudo_user.sh
#!/bin/bash

echo "The login user is $SUDO_USER"

Now, we execute the script with the sudo command:

$ sudo ./by_sudo_user.sh
[sudo] password for kent: 
The login user is kent

Great! It reports the original login user kent.

However, the $SUDO_USER variable is set only if our script is called with sudo. If a regular user calls the script directly, the $SUDO_USER variable is empty:

kent$ ./by_sudo_user.sh 
The login user is

To make our script work in both cases, we can use Bash’s parameter substituion ${parameter:-default} in the script.

${parameter:-default} means, if the parameter has been set, then we take its value. Otherwise, we take the default value. 

Here, the default part can be a fixed value, a shell variable, or a command substitution, and so on. We’ll see them in action in later examples.

Let’s come back to our script. We’ll first check the $SUDO_USER variable:

  • If it has been set, it means the user calls the script with sudo, and the value in $SUDO_USER is the login user
  • Otherwise, if the $SUDO_USER variable isn’t set, we can take either the value of the $USER variable or the output of the whoami command

Next, let’s change the script to cover this check:

kent$ cat ./by_sudo_user.sh
#!/bin/bash

echo "The login user is ${SUDO_USER:-$USER}"
echo "The login user is ${SUDO_USER:-$(whoami)}"

In the modified script above, we’ve shown two alternatives to address the usage of parameter substitution.

Finally, let’s test if it works as we expected:

kent$ ./by_sudo_user.sh 
The login user is kent
The login user is kent

kent$ sudo ./by_sudo_user.sh
[sudo] password for kent: 
The login user is kent
The login user is kent

The output above shows our script works for both cases. Thus, the problem has been solved.

5. Conclusion

When we write shell scripts, we may get the current login user by simply reading the $USER variable or calling the whoami command. However, this approach will fail if the script is called with the sudo command.

In this article, first, we discussed a common pitfall to solve this problem, using the who command. Next, we addressed two different ways to get the current login user in the shell script: the logname command and the $SUDO_USER variable.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.