概述
在实际工作中,曾经遇到切换用户环境变量无法加载的问题。其原因就是对su 和su -的区别认识有问题。
1、su命令:su不会读取目标用户的环境配置文件
2、su - 命令:su - 读取目标用户的环境配置文件
总结: su 命令与 su - 命令之间有什么区别呢?
前者在切换到 root 用户之后仍然保持旧的(或者说原始用户的)环境,也就是说,su gpadmin,虽然切到了gpadmin用户,但是其工作目录、环境变量依旧是root.
而后者则是创建一个新的环境(由 gpamin 用户 ~/.bashrc 文件所设置的环境),工作目录也同样切换到了gpadmin的家目录.
两种方法只差了一个字符 -,会有比较大的差异:
- 如果加入了 - 参数,那么是一种 login-shell 的方式,意思是说切换到另一个用户 之后,当前的 shell 会加载 对应的环境变量和各种设置;
- 如果没有加入 - 参数,那么是一种 non-login-shell 的方式,意思是说我现在切换到了 ,但是当前的 shell 还是加载切换之前的那个用户的环境变量以及各种设置。
总结 :具体使用哪种方式切换用户看个人需求:
- 如果不想因为切换到另一个用户导致自己在当前用户下的设置不可用,那么用 non-login-shell 的方式;
- 如果切换用户后,需要用到该用户的各种环境变量(不同用户的环境变量设置一般是不同的),那么使用 login-shell 的方式。
3、sudo和su有何区别呢?(update 2021年3月29日23:03:27)
su 是表示 switch user ,就是切换用户 。
sudo 的英文全称是 super user do,即以超级用户(root 用户)的方式执行命令。这里的 sudo 和之前 su 表示的 switch user 是不同的,这点需要注意,很容易搞混。
在切换用户时,时长使用这些命令切来切去,但对其细节掌握不够.
两个命令的最大区别是:
- sudo 命令需要输入当前用户的密码
- su 命令需要输入 root 用户的密码。
区别1:
sudo 命令只允许使用提升的权限运行单个命令
su 命令会启动一个新的 shell,同时允许使用 root 权限运行尽可能多的命令,直到明确退出登录。
因此su 命令的默认行为是有风险的,因为用户很有可能会忘记他们正在以 root 用户身份进行工作. 所以sudo相对更加安全.
区别2:
- sudo 命令是以目标用户(默认情况下是 root 用户)的身份执行命令,但是它们会使用 sudoer 所配置的用户名来记录是谁执行命令
- su 命令是无法直接跟踪记录用户切换到 root 用户之后执行了什么操作。
如果新用户不在sudoer文件中,此时是无法获取root权限的
sudotest is not in the sudoers file. This incident will be reported.
3、sudo的工作原理
一个用户能否使用 sudo 命令,取决于 /etc/sudoers 文件的设置。
/etc/sudoers 也是一个文本文件,但是因其有特定的语法,我们不要直接用 vim 或者 vi 来编辑它,需要用 visudo 这个命令。输入这个命令之后就能直接编辑 /etc/sudoers 这个文件了。
注意只有root用户才可以用visudo
解释下每一行的格式:
- 第一个表示用户名,如 root 、gpadmin等;
- 接下来等号左边的 ALL 表示允许从任何主机登录当前的用户账户;
- 等号右边的 ALL 表示:这一行行首对一个的用户可以切换到系统中任何一个其它用户;
- 行尾的 ALL 表示:当前行首的用户,能以 root 用户的身份下达什么命令,ALL 表示可以下达任何命令。
gpadmin那一行有个 NOPASSWD 关键字,这就是表明 gpadmin这个用户在请求 sudo 时不需要输入密码
添加sudoer用户
sudo为何会有问题呢?
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
使用root用户用visudo编辑完sudoer文件之后一定要确保/etc/sudoers的权限正确。
撤销文件的写权限。
[gpadmin@gptest01 ~]$ su - sudoer Password: [sudoer@gptest01 ~]$ tail -n 3 /etc/shadow tail: cannot open `/etc/shadow' for reading: Permission denied [sudoer@gptest01 ~]$ [sudoer@gptest01 ~]$ sudo tail -n 3 /etc/shadow dockerroot:!!:18495:::::: nagios:!!:18760:::::: sudoer:$6$2egw26NX$r0cvdgY7/M5tsRcn4holqys.SlDLvsZwrOxKGmdrA3Nu2r1ifWE3S34VKBVDOLxd0DnvwHQ4Wo9B0WuExx0ou/:18919:0:99999:7:::
etc/sudoers 文件赋予某种用户 sudo 权限时,必须要确定该用户是可信任 的,不会对系统造成恶意破坏,否则将所有 root 权限都赋予该用户将会有非常大的危险。
4、实操
4.1 跨用户执行命令
一般情况下先切换到另一个用户(root 或者 test_user),在哪个用户的状态下执行命令,最后输入 exit 返回当前用户。
如果不想切换用户直接在当前用户下,以另一个用户的方式执行命令,执行结束后就返回当前用户。这就得用到 -c 参数。
在脚本编写中,经常需要切换到gpadmin用户下去执行脚本。
例如
#!/bin/bash # @date 2021年2月22日10:12:56 # @author ninesun # @desc # 1. copy query to file # 2. get copy qty # dbname^schemaname^tablename^start^end #su - gpadmin <<EOF #psql -d qmstst -v v1="'$dateFrom'" -f /home/scripts/geneSqlCnt.sql >> usrSqlCnt.txt; #exit; #EOF if [ $# == 9 ]; then datebeg=$1 dateend=$2 tablename=$3 schemaname=$4 dbname=$5 query_condition=$6 query_column=$7 query_condition1=$8 else #echo "plese input start && end time && tablename,eg '2020-05-18 09:00:00' '2020-05-18 09:20:00' 'wpp_adefect_glass_f' 'db_timestamp' " exit 1 fi EXPORT_START_DATE=$1 EXPORT_END_DATE=$2 TABLE_NAME=$3 SCHEMA_NAME=$4 DB_NAME=$5 QUERY_CONDITION=$6 QUERY_COLUMN=$7 QUERY_CONDITION1=$8 path="/mnt/dataTransfer" #path_local="/mnt/gptransferTest" path_local="/aplog/data/GP4toGP6" current_path=`pwd` #echo $EXPORT_START_DATE #echo $EXPORT_END_DATE #echo "$*" #echo "$@" year=${EXPORT_START_DATE:0:4} month=${EXPORT_START_DATE:5:2} day=${EXPORT_START_DATE:8:2} #echo "substr : $year$month$day" #su - gpadmin <<EOF #echo "user name = ${USER}" su - gpadmin <<EOF psql -h hostname -d $DB_NAME -c "copy (select $QUERY_COLUMN from $DB_NAME.$SCHEMA_NAME.$TABLE_NAME where 1=1 and $QUERY_CONDITION >= '$EXPORT_START_DATE' and $QUERY_CONDITION < '$EXPORT_END_DATE') to '$path_local/$DB_NAME^$SCHEMA_NAME^$TABLE_NAME.csv' WITH DELIMITER AS ','" EOF # 获取状态码 t=$? echo "status $t" if [[ $t -eq 0 ]];then exit 99; # shell 执行返回指定状码 # echo "table name : $TABLE_NAME dump Successfully" else exit 100; # shell 执行返回指定状码 # echo "table name : $TABLE_NAME dump failed" fi #echo "$t"
shell中使用su - gpadmin << EOF.... EOF
这个明显太繁琐,可以使用-c参数
~]# su - gpadmin -c "pwd" /home/gpadmin