It is often necessary to run commands with sudo in bash scripts or directly in the script itself, but this raises a series of problems. For example, when using sudo, should the variable ~ or $HOME in the script, which refers to the user folder, point to my real user folder such as /home/pi, or to the super administrator's 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, so what should I do? First of all, let me share my experience: command line permission execution can be divided into the following five situations from the performance point of view:
Many variables and environment variables will often be confused in these 4 situations! (The chaos refers to us, not the computer) Also, here’s a little tip. We all know that the ~ variable refers to the current user's directory. In fact, a variable in the format of ~abc can point to the user directory of a specified user, such as ~pi will point to /home/pi, or ~ubuntu will point to /home/ubuntu. Let’s clarify our thoughts: There is no problem when executing scripts normally, such as ./test.sh. There is no problem even if sudo appears in the script, such as sudo apt-get update. So suppose my real user is pi, and my HOME directory is /home/pi. Now I want to find the correct solution under the execution mode of sudo ./test.sh. # (Not recommended!) $ whoami >>> root # Different from whoami, it can indicate which users are currently logged into the computer, including everyone logged in locally and through ssh. $ who am i >>> Some machines show empty >>> Mac shows: pi ttys001 Nov 26 16:57 # Equivalent to whoami (not recommended!) $ echo $USER >>> root # User home directory location (not reliable and not recommended!) echo $HOME >>> /root $ User home directory location, equivalent to $HOME (not recommended!) $ echo ~ >>> /root # Use the environment variable LOGNAME directly $ echo $LOGNAME >>> root # Explicitly call the environment variable LOGNAME $ printenv LOGNAME >>> root # SUDO_USER is an environment variable in root's ENV. # At the same time, ordinary users do not have env, only root users can display it $ sudo echo $SUDO_USER >>> pi # Display the call environment variable SUDO_USER (not recommended!) # From the results, you can see that even if the script is executed as sudo, it will be different if sudo is added to the script! $ printenv SUDO_USER >>> pi $ sudo printenv SUDO_USER >>> root From the above test, we can see that if we use sudo to execute the bash script, many variables are "unreliable". In Stackoverflow, the more consistent tendency is to use the $SUDO_USER environment variable. And in the test, it is indeed the most "stable", that is, it can be consistent under different permissions and OS systems (only for systems with sudo). Now that we have the username, we can use a command like ~pi to get the home directory /home/pi, but! Now the problem arises again: when typing manually, we can get the correct address of ~pi, but the script does not recognize what ~pi is. At most, it is a string, not a variable. In this case, we can't use the ~abc method, but use the old-fashioned but definitely not confusing method: Manually, you can directly open passwd to view it, but it is more troublesome in the script. The most convenient way is to use the system command getent, that is, Get Entries command, to obtain the information of the specified user: $ getent passwd pi >>> pi:x:1000:1000:,,,:/home/pi:/bin/bash So, what's left is to take out /home/pi, which we can easily take out using cut. So the whole process is as follows: me=$SUDO_USER myhome=`getent passwd $me | cut -d: -f 6` Successfully got /home/pi! Going a step further, what if the script is not run as sudo? At this time, there is no SUDO_USER variable in the environment variables of the root user and ordinary users. Then we need to add a step of judgment: me=${SUDO_USER:-$LOGNAME} myhome=`getent passwd $me | cut -d: -f 6` That is, if SUDO_USER is empty, $LOGNAME is used normally to get the current user. Why not use $LOGNAME instead of $USER? Because USER is not available on every system, but LOGNAME is available on all *nix systems. renew Since some OS cannot correctly obtain LOGNAME, the uid method is used to obtain the user path: HOUSE=`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6` Update again MacOS does not have /etc/passwd and does not support the getent passwd <UID> method to obtain user information, but the contents of the $USER and $HOME variables can remain unchanged under sudo. So change it to the following: HOUSE=${$(`getent passwd ${SUDO_UID:-$(id -u)} | cut -d: -f 6`):-$HOME} That is, if the getent method cannot obtain the content, the value of $HOME is directly obtained. Update again Because bash does not support the above nested ternary expression, it needs to be separated: HOUSE="`cat /etc/passwd |grep ${SUDO_UID:-$(id -u)} | cut -d: -f 6`" HOUSE=${HOUSE:-$HOME} Update again and again If it is root, grep uid will match all lines containing 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} The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM. You may also be interested in:
|
<<: React event mechanism source code analysis
>>: mysql5.7.19 winx64 installation and configuration method graphic tutorial (win10)
In the previous article https://www.jb51.net/arti...
01. Infinity Font Download 02. Banda Font Download...
Table of contents Introduction: Installation of e...
Let me share with you a creative opening realized...
for loop Basic syntax format: for(initialize vari...
Ubuntu is a relatively popular Linux desktop syst...
Nginx can use the limit_req_zone directive of the...
Table of contents Overview Hash Properties Host p...
Table of contents 1. How to represent the current...
Sometimes we need to control whether HTML elements...
introduce Have you ever spent a whole day trying ...
1. Idea It only took 6 seconds to insert 1,000,00...
Table of contents one. environment two. Precautio...
Achieve results Implementation Code html <div ...
Introduction Use simple jQuery+CSS to create a cus...