su(switch user)用來切換使用者的命令。預設情況下不會載入目標使用者的環境變數。
而 -
是 su command 的 option,用於告訴系統模擬完整的登入行為,包括載入目標使用者的登入 shell、初始化的環境變數(例如 $PATH)、以及執行目標使用者的 shell 啟動腳本(如 .bashrc 或 .bash_profile)。
Example
Create new user account - lucy
kanglin@lab1:~$ sudo adduser lucy
[sudo] password for kanglin:
Adding user `lucy' ...
Adding new group `lucy' (1001) ...
Adding new user `lucy' (1001) with group `lucy' ...
Creating home directory `/home/lucy' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for lucy
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n] Y
Declare a variable on user kanglin
kanglin@lab1:~$ export location="Neihu"
kanglin@lab1:~$ printenv location
Neihu
Switch to user lucy without -
kanglin@lab1:~$ su lucy
Password:
lucy@lab1:/home/kanglin$ printenv location
Neihu
lucy@lab1:/home/kanglin$ exit
exit
Swithc to user lucy with -
kanglin@lab1:~$ su - lucy
Password:
lucy@lab1:~$ printenv location
lucy@lab1:~$
Explanation
在第一個使用者帳號中(kanglin),我們使用 export 命令宣告並導出了一個環境變數 location,它的值為 Neihu。這表示該變數在當前使用者的環境中可用,並且對任何在該 shell 中啟動的子進程(如新的 shell 或應用程式)也可見。
當使用 su lucy 切換到第二個使用者帳號(lucy)時,該命令會啟動一個新的 shell,但保留了原使用者的環境變數(包括 location),因為它並沒有模擬完整的登入行為。
當使用 su - lucy 切換到 lucy 時,則會模擬完整的登入行為。這包括:
載入目標使用者(lucy)的登入 shell 環境。
清除當前 shell 的環境變數(除了少數預設變數,如 HOME 和 PATH 等)。
重新載入目標使用者的環境配置(如 .bash_profile 或 .profile 等)。
因此,在 su - lucy 的情況下,因為新的登入 shell 不會繼承原使用者的環境變數,變數 location 不再可見。
ChatGPT 的補充
export 的作用:
使用 export 將變數設定為環境變數,使它對該 shell 及其子進程可見。
若僅是 location="Neihu" 而沒有 export,變數僅對當前 shell 的範圍有效,子進程無法存取。
su vs su - 的行為差異:
su username:只切換使用者,但保留當前的環境變數,類似於在原環境中啟動一個新的 shell。
su - username:模擬完整的登入行為,清除原來的環境變數,並重新載入新使用者的登入環境。
如何在 su - 的情況下傳遞變數:
如果希望變數在執行 su - 後仍然可見,可以在切換帳號前,將變數直接寫入目標使用者的環境設定檔案(如 .bashrc 或 .profile)中。例如:
echo 'export location="Neihu"' >> /home/lucy/.bashrc
或者臨時地傳遞變數:
su - lucy -c 'export location="Neihu"; bash'