1. 準備工作
因為本篇部落格中涉及到使用者切換,是以我需要提前準備好幾個測試使用者,友善後續切換。
Linux 中建立使用者的指令是 useradd ,一般系統中這個指令對應的路徑都在 PATH 環境變量裡,如果直接輸入 useradd 不管用的話,就用絕對路徑名的方式:/usr/sbin/useradd 。
useradd 建立使用者指令隻有 root 使用者才能執行,我們先從普通使用者 ubuntu 切換到 root 使用者(如何切換後文會介紹):
ubuntu@VM-0-14-ubuntu:~$ su -
Password: # 輸入 root 使用者登入密碼
root@VM-0-14-ubuntu:~# useradd -m test_user # 帶上 -m 參數
root@VM-0-14-ubuntu:~# ls /home
test_user ubuntu # 可以看到 /home 目錄下面有兩個使用者了
因為還沒有給建立的使用者 test_user 設定登入密碼,這就導緻我們無法從普通使用者 ubuntu 切換到 test_user,是以接下來,我們需要用 root 來設定 test_user 的登入密碼。需要用到 passwd 指令:
root@VM-0-14-ubuntu:~# passwd test_user
Enter new UNIX password: # 輸出 test_user 的密碼
Retype new UNIX password:
passwd: password updated successfully
root@VM-0-14-ubuntu:~#
接着我們輸入
exit
退出 root 使用者到 普通使用者 ubuntu:
root@VM-0-14-ubuntu:~# exit
logout
ubuntu@VM-0-14-ubuntu:~$
可以看到,指令提示符前面已經由 root 變成 ubuntu,說明我們現在的身份是 ubuntu 使用者。
2. su 指令介紹及主要用法
首先需要解釋下 su 代表什麼意思。
之前一直以為 su 是 super user,查閱資料之後才知道原來表示 switch user。
知道 su 是由什麼縮寫來的之後,那麼它提供的功能就顯而易見了,就是切換使用者。
2.1 - 參數
su
的一般使用方法是:
su <user_name>
或者
su - <user_name>
兩種方法隻差了一個字元 -,會有比較大的差異:
如果加入了 - 參數,那麼是一種 login-shell 的方式,意思是說切換到另一個使用者 之後,目前的 shell 會加載 對應的環境變量和各種設定;
如果沒有加入 - 參數,那麼是一種 non-login-shell 的方式,意思是說我現在切換到了 ,但是目前的 shell 還是加載切換之前的那個使用者的環境變量以及各種設定。
光解釋會比較抽象,我們看一個例子就比較容易了解了。
我們首先從 ubuntu 使用者以 non-login-shell 的方式切換到 root 使用者,比較兩種使用者狀态下環境變量中 PWD 的值(su 指令不跟任何 ,預設切換到 root 使用者):
ubuntu@VM-0-14-ubuntu:~$ env | grep ubuntu
USER=ubuntu
PWD=/home/ubuntu # 是 /home/ubuntu
HOME=/home/ubuntu
# 省略......
ubuntu@VM-0-14-ubuntu:~$ su # non-login-shell 方式
Password: # 輸入 root 使用者登入密碼
root@VM-0-14-ubuntu:/home/ubuntu# env | grep ubuntu
PWD=/home/ubuntu # 可以發現還是 /home/ubuntu
root@VM-0-14-ubuntu:/home/ubuntu#
我們的确是切換到 root 使用者了,但是 shell 環境中的變量并沒有改變,還是用之前 ubuntu 使用者的環境變量。
接着我們從 ubuntu 使用者以
login-shell
的方式切換到 root 使用者,同樣比較兩種使用者轉台下環境變量中
PWD
的值:
ubuntu@VM-0-14-ubuntu:~$ env | grep ubuntu
USER=ubuntu
PWD=/home/ubuntu # 是 /home/ubuntu
HOME=/home/ubuntu
# 省略.......
ubuntu@VM-0-14-ubuntu:~$ su - # 是 login-shell 方式
Password:
root@VM-0-14-ubuntu:~# env | grep root
USER=root
PWD=/root # 已經變成 /root 了
HOME=/root
MAIL=/var/mail/root
LOGNAME=root
root@VM-0-14-ubuntu:~#
可以看到用 login-shell 的方式切換使用者的話,shell 中的環境變量也跟着改變了。
總結:具體使用哪種方式切換使用者看個人需求:
如果不想因為切換到另一個使用者導緻自己在目前使用者下的設定不可用,那麼用 non-login-shell 的方式;
如果切換使用者後,需要用到該使用者的各種環境變量(不同使用者的環境變量設定一般是不同的),那麼使用 login-shell 的方式。
2.2 切換到指定使用者
前面已經介紹了,如果 su 指令後面不跟任何 ,那麼預設是切換到 root 使用者:
ubuntu@VM-0-14-ubuntu:~$ su -
Password: # root 使用者的密碼
root@VM-0-14-ubuntu:/home/ubuntu#
因為我們在 1. 準備工作 部分已經建立了一個 test_user 使用者,并且我們也知道 test_user 使用者的登入密碼(root 使用者設定的),我們就能從 ubuntu 使用者切換到 test_user 使用者:
ubuntu@VM-0-14-ubuntu:~$ su - test_user
Password: # test_user 使用者的密碼
$
2.3 -c 參數
前面的方法中,我們都是先切換到另一個使用者(root 或者 test_user),在哪個使用者的狀态下執行指令,最後輸入 exit 傳回目前 ubuntu 使用者。
還有一種方式是:不需要先切換使用者再執行指令,可以直接在目前使用者下,以另一個使用者的方式執行指令,執行結束後就傳回目前使用者。這就得用到 -c 參數。
具體使用方法是:
su - -c "指令串" # 以 root 的方式執行 "指令串"
我麼看個例子:
ubuntu@VM-0-14-ubuntu:~$ cat /etc/shadow
cat: /etc/shadow: Permission denied # ubuntu 使用者不能直接檢視 /etc/shadow 檔案内容
ubuntu@VM-0-14-ubuntu:~$ su - -c "tail -n 4 /etc/shadow"
Password: # 輸入 root 使用者密碼
ubuntu:$1$fZKcWEDI$uwZ64uFvVbwpHTbCSgim0/:18352:0:99999:7:::
ntp:*:17752:0:99999:7:::
mysql:!:18376:0:99999:7:::
test_user:$6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS//89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
ubuntu@VM-0-14-ubuntu:~$ # 執行完馬上傳回 ubuntu 使用者而不是 root 使用者
這種執行方式和後面要介紹的 sudo 很像,都是臨時申請一下 root 使用者的權限。但還是有差異,我們接着往後看。
3. sudo 指令介紹及主要用法
首先還是解釋下 sudo 指令是什麼意思。
sudo 的英文全稱是 super user do,即以超級使用者(root 使用者)的方式執行指令。這裡的 sudo 和之前 su 表示的 switch user 是不同的,這點需要注意,很容易搞混。
我們先介紹 sudo 指令能做什麼事情,然後說明為何能做到這些,以及如何做到這些。
我們開始。
3.1 主要用法
我們在 Linux 中經常會碰到 Permission denied 這種情況,比如以 ubuntu 使用者的身份檢視 /etc/shadow 的内容。因為這個檔案的内容是隻有 root 使用者能檢視的。
那如果我們想要檢視怎麼辦呢?這時候就可以使用 sudo :
ubuntu@VM-0-14-ubuntu:~$ tail -n 3 /etc/shadow
tail: cannot open '/etc/shadow' for reading: Permission denied # 沒有權限
ubuntu@VM-0-14-ubuntu:~$ sudo !! # 跟兩個驚歎号
sudo tail -n 3 /etc/shadow
ntp:*:17752:0:99999:7:::
mysql:!:18376:0:99999:7:::
test_user:$6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS//89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
ubuntu@VM-0-14-ubuntu:~$
執行個體中,我們使用了 sudo !! 這個小技巧,表示重複上面輸入的指令,隻不過在指令最前面加上 sudo 。
因為我已經設定了 sudo 指令不需要輸入密碼,是以這裡 sudo !! 就能直接輸出内容。如果沒有設定的話,需要輸入目前這個使用者的密碼,例如本例中,我就應該輸入 ubuntu 使用者的登入密碼。
兩次相鄰的 sudo 操作,如果間隔在 5min 之内,第二次輸入 sudo 不需要重新輸入密碼;如果超過 5min,那麼再輸入 sudo 時,又需要輸入密碼。是以一個比較省事的方法是設定 sudo 操作不需要密碼。後面介紹如何設定。
sudo 除了以 root 使用者的權限執行指令外,還有其它幾個用法,這裡做簡單介紹。
切換到 root 使用者:
sudo su -
這種方式也能以 login-shell 的方式切換到 root 使用者,但是它和 su - 方法是由差別的:
前者輸入 sudo su - 後,需要提供目前使用者的登入密碼,也就是 ubuntu 使用者的密碼;
後者輸入 su - 後,需要提供 root 使用者的登入密碼。
還有一個指令:
sudo -i
這個指令和 sudo su - 效果一緻,也是切換到 root 使用者,也是需要提供目前使用者(ubuntu 使用者)的登入密碼。
我們現在切換到 test_user 使用者,嘗試顯示 /etc/shadow 檔案的内容:
ubuntu@VM-0-14-ubuntu:~$ su - test_user
Password: # test_user 的密碼
$ sudo cat /etc/shadow
[sudo] password for test_user: # test_user 的密碼
test_user is not in the sudoers file. This incident will be reported.
$
我們會看到倒數第二行中的錯誤提示資訊,我們無法檢視 /etc/shadow 的内容,這是為什麼?為什麼 ubuntu 可以使用 sudo 但是 test_user 不行呢?
這就涉及到 sudo 的工作原理了。
3.2 sudo 工作原理
一個使用者能否使用 sudo 指令,取決于 /etc/sudoers 檔案的設定。
從 3.1 節中我們已經看到,ubuntu 使用者可以正常使用 sudo ,但是 test_user 使用者卻無法使用,這是因為 /etc/sudoers 檔案裡沒有配置 test_user。
/etc/sudoers 也是一個文本檔案,但是因其有特定的文法,我們不要直接用 vim 或者 vi 來編輯它,需要用 visudo 這個指令。輸入這個指令之後就能直接編輯 /etc/sudoers 這個檔案了。
需要說明的是,隻有 root 使用者有權限使用 visudo 指令。
我們先來看下輸入 visudo 指令後顯示的内容。
輸入(root 使用者):
root@VM-0-14-ubuntu:~# visudo
輸出:
# User privilege specification
root ALL=(ALL:ALL) ALL
# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
ubuntu ALL=(ALL:ALL) NOPASSWD: ALL
解釋下每一行的格式:
第一個表示使用者名,如 root 、ubuntu 等;
接下來等号左邊的 ALL 表示允許從任何主機登入目前的使用者賬戶;
等号右邊的 ALL 表示:這一行行首對一個的使用者可以切換到系統中任何一個其它使用者;
行尾的 ALL 表示:目前行首的使用者,能以 root 使用者的身份下達什麼指令,ALL 表示可以下達任何指令。
我們還注意到 ubuntu 對應的那一行有個 NOPASSWD 關鍵字,這就是表明 ubuntu 這個使用者在請求 sudo 時不需要輸入密碼,到這裡就解釋了前面的問題。
同時我們注意到,這個檔案裡并沒有 test_user 對應的行,這也就解釋了為什麼 test_user 無法使用 sudo 指令。
接下來,我們嘗試将 test_user 添加到 /etc/sudoers 檔案中,使 test_user 也能使用 sudo 指令。我們在最後一行添加:
test_user ALL=(ALL:ALL) ALL # test_user 使用 sudo 需要提供 test_user 的密碼
接下來我們再在 test_user 賬戶下執行
sudo
:
ubuntu@VM-0-14-ubuntu:~$ su - test_user
Password:
$ tail -n 3 /etc/shadow
tail: cannot open '/etc/shadow' for reading: Permission denied
$ sudo tail -n 3 /etc/shadow # 加上 sudo
ntp:*:17752:0:99999:7:::
mysql:!:18376:0:99999:7:::
test_user:$6$.ZY1lj4m$ii0x9CG8h.JHlh6zKbfBXRuolJmIDBHAd5eqhvW7lbUQXTRS//89jcuTzRilKqRkP8YbYW4VPxmTVHWRLYNGS/:18406:0:99999:7:::
$
可以看到,現在已經可以使用 sudo 了。
3.3 思考
我們已經看到了,如果一個使用者在 /etc/sudoers 檔案中,那麼它就具有 sudo 權限,就能通過 sudo su - 或者 sudo -i 等指令切換到 root 使用者了,那這時這個使用者就變成 root 使用者了,那這不對系統造成很大的威脅嗎?
實際上的确是這樣的。是以如果在編輯 /etc/sudoers 檔案賦予某種使用者 sudo 權限時,必須要确定該使用者是可信任的,不會對系統造成惡意破壞,否則将所有 root 權限都賦予該使用者将會有非常大的危險。
當然,root 使用者也可以編輯 /etc/sudoers 使使用者隻具備一部分權限,即隻能執行一小部分指令。有興趣的讀者可以參考 Reference 部分第二條,這篇文章不再贅述。
4. 二者的差異對比
我們已經看到:
使用 su - ,提供 root 賬戶的密碼,可以切換到 root 使用者;
使用 sudo su - ,提供目前使用者的密碼,也可以切換到 root 使用者
兩種方式的差異也顯而易見:如果我們的 Linux 系統有很多使用者需要使用的話,前者要求所有使用者都知道 root 使用者的密碼,這顯然是非常危險的;後者是不需要暴露 root 賬戶密碼的,使用者隻需要輸入自己的賬戶密碼就可以,而且哪些使用者可以切換到 root,這完全是受 root 控制的(root 通過設定 /etc/sudoers 實作的),這樣系統就安全很多了。
一般都是推薦使用 sudo 方式。
References
https://www.rootusers.com/the-difference-between-su-and-sudo-commands-in-linux/《鳥哥的 Linux 私房菜》13.4 節:使用者身份切換
https://github.com/ustclug/Linux101-docs/blob/master/docs/Ch05/index.md https://www.maketecheasier.com/differences-between-su-sudo-su-sudo-s-sudo-i/ https://stackoverflow.com/questions/35999671/whats-the-difference-between-sudo-i-and-sudo-su?r=SearchResults https://www.zhihu.com/question/51746286 https://www.linuxidc.com/Linux/2017-06/144916.htm