An example of how the linux Bash script identifies the user

  • 2020-12-26 06:18:07
  • OfStack

It is often necessary to add sudo commands to bash scripts or directly to the scripts themselves, but this causes a series 1 problem.

For example, when using sudo, the ~ or $HOME in the script refers to the user folder variable. Should I point to my real user folder like /home/pi, or to the super admin user folder /root/?

It actually points to the /root/ folder, which we definitely don't want. But many commands, such as installing a program, have to use sudo. What about that?

First, let's talk about the experience: command line permission execution, from the perspective of performance, can be divided into the following five cases:

admin-manual: Ordinary user hand - tapping commands sudo-manual: Add sudo to the hand command admin-bash: Execute the bash script as a normal user sudo-bash: Execute the bash script as sudo root-any: Login as root user

Many variables, environment variables in these 4 cases, will often appear confusion! (Chaos means ourselves, not computers.)

Plus, here's a little tip.

Until ~ variables point to the current user directory, in fact ~abc can point to the user directory of the specified user, e.g. ~pi will point to /home/pi, or ~ubuntu to /home/ubuntu.

1. Clear up the following thoughts:

There is no problem with normal execution of scripts such as./ test. sh, even if sudo like sudo ES55en-ES56en update appears in the script.
That is, only if sudo is executed against the entire script, such as sudo. / test. sh, will serious problems occur!

So let's say my real user is pi and the HOME directory is /home/pi. Now I want to find the correct solution in the execution mode of sudo. / test. sh.
The following are the various statements and variables in the script and the results displayed:


#  (Not recommended!) 
$ whoami
>>> root

#  Different from the whoami , can indicate which users are currently logged in to the computer, including native login and ssh The owner of the login 
$ who am i
>>>  On some machines the display is empty 
>>> Mac Displayed on the : pi ttys001 Nov 26 16:57

#  Is equivalent to whoami  (Not recommended!) 
$ echo $USER
>>> root

#  User home directory location  ( Not recommended!) 
echo $HOME
>>> /root

$  User home directory location, equal to $HOME  (Not recommended!) 
$ echo ~
>>> /root

#  Use environment variables directly LOGNAME
$ echo $LOGNAME
>>> root

#  Explicitly calling an environment variable LOGNAME 
$ printenv LOGNAME
>>> root


# SUDO_USER is root the ENV Environment variables in, 
#  At the same time ordinary users env There is no, there is only root The user can display it 
$ sudo echo $SUDO_USER
>>> pi


#  Displays the call environment variable SUDO_USER  (Not recommended!) 
#  As you can see from the results, even if sudo Id execution of the script, the script inside whether to add sudo It will be different! 
$ printenv SUDO_USER
>>> pi
$ sudo printenv SUDO_USER
>>> root

As you can see from the above tests, many variables would be "unreliable" if we were using sudo to execute the bash script.

In Stackoverflow, the tendency to compare the sex of 1 is to use the environment variable $SUDO_USER. Indeed, in the tests, it was the most "stable", always 1 under different permissions and OS systems (sudo only).

So now that we have a username, we can get the home directory /home/pi using commands like ~pi, but!

Here's the problem: we can get the correct address of ~pi by tapping, but the script doesn't recognize ~pi as anything, at most a string, not like variable 1.

In this case, instead of using the ~abc method, we use the old but definitely not chaotic method:
See directly from /etc/passwd.

Manually, you can directly open passwd view, the script inside is more troublesome, the most convenient is to use the system command getent, Get Entries command, to get the information of the specified user:


$ getent passwd pi
>>> pi:x:1000:1000:,,,:/home/pi:/bin/bash

So, all that's left is that you take the /home/pi out of it, so we can just take it out with cut.

So the whole process is as follows:


me=$SUDO_USER
myhome=`getent passwd $me | cut -d: -f 6`

Get /home/pi!

One more step, what if the script doesn't run in sudo mode? There is no SUDO_USER variable in the environment variable of both root users and ordinary users. Then you need to add one more step:


me=${SUDO_USER:-$LOGNAME}
myhome=`getent passwd $me | cut -d: -f 6`

That is, if SUDO_USER is empty, then $LOGNAME is normally used to get the current user. Why not use $LOGNAME instead of $USER? Because USER is not available for every system, but LOGNAME is available for *nix systems.

update

As part OF OS cannot get LOGNAME correctly, so series 1 uses uid to get the user path:


HOUSE=`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6`

To update the

MacOS does not have /etc/passwd and does not support getent passwd < UID > Method to get user information, but the $USER and $HOME variables are also kept unchanged under sudo.

So change to the following:


HOUSE=${$(`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6`):-$HOME}

That is, if the getent method cannot fetch the content, the value of $HOME is directly fetched.

Again to update the

Since bash does not support the nested 3-element expression above, it is broken:


HOUSE="`cat /etc/passwd |grep ${SUDO_UID:-$(id -u)} | cut -d: -f 6`"
HOUSE=${HOUSE:-$HOME}

And then update it again

If it is root, grep uid will match all rows with 0 in passwd, so it should be improved as follows:


HOUSE="`cat /etc/passwd |grep ^${SUDO_USER:-$(id -un)}: | cut -d: -f 6`"
HOUSE=${HOUSE:-$HOME}

Related articles: