su 指令:su 與 su - 的差異、sudo su 與 sudo -i,以及切換帳號的方法
在 Linux 上不登出目前的帳號、改用其他帳號執行指令時,就使用 su 指令。在 AlmaLinux 9 伺服器上從 root 帳號對無法登入的系統帳號 daemon 執行 su 並比較的結果,一個連字號就讓工作資料夾和 PATH 改變,而且要指定 shell 指令才會執行。
下面的輸出是在 AlmaLinux 9.8 伺服器(root 帳號)和 Debian 12 伺服器(一般帳號)上執行的結果。詢問密碼的畫面和 sudo 沒有在正式運作的伺服器上執行,而是依官方手冊整理;PATH 值的一部分和模擬器中 util-linux 的修補版本號碼已換成範例值。
1️⃣ su 指令的用法
基本格式是 [su 帳號名稱],省略帳號名稱時會切換成 root。在新的 shell 輸入 exit,那個 shell 就會結束,回到執行 su 的原本帳號的 shell。
從一般帳號執行時,要在 Password: 那一行輸入要切換的帳號的密碼(依 PAM 預設設定)。這台伺服器的 /etc/pam.d/su 設定成執行者是 root 時略過驗證,所以從 root 帳號切換到 daemon 時沒有詢問密碼。
su --help
Usage:
su [options] [-] [<user> [<argument>...]]
Change the effective user ID and group ID to that of <user>.
A mere - implies -l. If <user> is not given, root is assumed.
Options:
-m, -p, --preserve-environment do not reset environment variables
-w, --whitelist-environment <list> don't reset specified variables
-g, --group <group> specify the primary group
-G, --supp-group <group> specify a supplemental group
-, -l, --login make the shell a login shell
-c, --command <command> pass a single command to the shell with -c
--session-command <command> pass a single command to the shell with -c
and do not create a new session
-f, --fast pass -f to the shell (for csh or tcsh)
-s, --shell <shell> run <shell> if /etc/shells allows it
-P, --pty create a new pseudo-terminal
-h, --help display this help
-V, --version display version
For more details see su(1).如說明所寫,連字號 [-] 是與 [-l] 相同的登入選項,寫在帳號名稱後面的引數會交給切換後帳號的 shell。AlmaLinux 9 伺服器的 su 來自 util-linux 2.37 套件,Debian 12 伺服器的 su 來自 2.38 套件。
su --versionsu from util-linux 2.38.1想切換的帳號能不能開啟 shell,看 getent passwd 中該帳號那一行的最後一欄就知道。
getent passwd daemondaemon:x:2:2:daemon:/sbin:/sbin/nologindaemon 的 shell 是 /sbin/nologin。登入用 shell 的位置寫著 nologin 的帳號,即使用 su 切換過去也不會開啟 shell。
2️⃣ su 與 su - 的差異
加上連字號(-)時,su 會開啟和用切換後帳號登入時相同的 shell。在 /tmp 資料夾裡,同一個指令不加連字號執行一次,加上連字號再執行一次。
su -s /bin/sh -c pwd daemon/tmpsu - -s /bin/sh -c pwd daemon/usr/sbin沒有連字號時工作資料夾仍是 /tmp,[su -] 則移到 daemon 的家目錄 /sbin。這台伺服器的 /sbin 是連到 /usr/sbin 的連結,所以 pwd 顯示 /usr/sbin。
環境變數只從 env 的輸出中挑出 HOME、USER、SHELL、PATH、LOGNAME 五行來比較。
su -s /bin/sh -c env daemon | grep -E '^(HOME|USER|SHELL|PATH|LOGNAME)='SHELL=/bin/sh
LOGNAME=daemon
HOME=/sbin
USER=daemon
PATH=/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/binsu - -s /bin/sh -c env daemon | grep -E '^(HOME|USER|SHELL|PATH|LOGNAME)='SHELL=/bin/sh
LOGNAME=daemon
HOME=/sbin
USER=daemon
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbinHOME、USER、LOGNAME 在兩種情況下都變成 daemon 的值。PATH 在沒有連字號時保留執行 su 的 root 的值,[su -] 則依登入設定重新決定。
依官方手冊,沒有連字號的 su 只改變 HOME 和 SHELL,只有在目標帳號不是 root 時才連 USER 和 LOGNAME 一起改變。因此從一般帳號不加連字號切換成 root 時,USER 會留著原本的帳號名稱。
顯示 shell 名稱的 [$0] 也不一樣。
su -s /bin/sh -c 'echo $0' daemonshsu - -s /bin/sh -c 'echo $0' daemon-sh[su -] 的 shell 名稱前面加上了連字號,顯示為 -sh。名稱以連字號開頭的 shell 會以登入 shell 運作,並讀取登入設定檔(依官方手冊)。兩種形式的差異如下。
| 比較 | su | su - |
|---|---|---|
| 工作資料夾 | 不變(/tmp) | 切換後帳號的家目錄(/usr/sbin) |
| HOME, USER, LOGNAME | daemon 的值 | daemon 的值 |
| PATH | 執行 su 的 root 的值 | 依登入設定重新決定 |
| shell 名稱($0) | sh | -sh(登入 shell) |
| 其他環境變數 | 保持原樣 | 只留下 TERM 等一部分,其餘清除(依官方手冊) |
官方手冊建議一律加上登入選項以免環境混在一起,並以 [--login] 代替連字號。沒有連字號的 su 會保留目前的資料夾和 PATH,所以想用其他帳號的設定確認指令時,結果可能和 [su -] 不同。
3️⃣ su -c 與 su -s 選項
不開啟 shell、只用其他帳號執行一個指令時,在 -c 後面寫上指令。對 nologin 帳號用 [su -c] 執行 id,出現的是拒絕訊息而不是指令結果。
su -c id daemonThis account is currently not available.用 -c 傳入的指令也是由帳號的 shell 接收並執行,所以 shell 是 nologin 時指令根本不會被執行。這時用 -s 指定要執行的 shell。
su -s /bin/sh -c id daemonuid=2(daemon) gid=2(daemon) groups=2(daemon)指定 /bin/sh 後,id 以 daemon 的 UID 2 執行。要用服務帳號確認檔案權限或指令結果時,就使用這個形式。
如果目標帳號的 shell 是像 nologin 這樣不在 /etc/shells 裡的受限 shell,只有 root 能用 -s 換 shell。依官方手冊,這時非 root 使用者指定的 -s 和 SHELL 變數會被忽略。
-c 後面的指令有空格時,用引號括起來當成一整塊傳入。su 會原樣傳回所執行指令的結束代碼,無法執行指令時傳回 126,找不到指令時傳回 127(依官方手冊)。
📌 主要選項:本文實際執行的結果
| 選項 | 作用 | 本文看到的結果 | |
|---|---|---|---|
| - | 開啟和用目標帳號登入時相同的 shell,並移到該帳號的家目錄 | 在 /tmp 不加連字號時 pwd 是 /tmp,加上後是 /usr/sbin,echo $0 為 -sh | |
| -c 指令 | 不開啟 shell,用目標帳號的 shell 執行一個指令 | 對 nologin 帳號 daemon 執行 su -c id daemon,出現 [This account is currently not available.] | |
| -s shell | 用指定的 shell 代替帳號設定的 shell 執行,受限 shell 帳號只限 root | su -s /bin/sh -c id daemon 得到 uid=2(daemon) gid=2(daemon) groups=2(daemon) | |
| --help | 顯示用法與選項清單 | Usage 行與 -m、-w、-g、-G、-l、-c、-f、-s、-P、-h、-V 選項清單 | |
| --version | 輸出版本資訊 | Debian 12 伺服器上為 su from util-linux 2.38.1 |
📎 其他選項:依官方手冊
| 選項 | 作用 | |
|---|---|---|
| -l | 與連字號(-)相同的登入選項,長名稱為 --login | |
| -m | 保留環境變數,也不改變 HOME、SHELL、USER、LOGNAME,與登入選項一起使用時會被忽略(同 -p) | |
| -w 清單 | 登入選項清空環境時保留以逗號列出的變數,HOME、SHELL、USER、LOGNAME、PATH 會重新決定 | |
| -g 群組 | 指定主要群組,只限 root | |
| -G 群組 | 指定補充群組,只限 root,沒有 -g 時第一個補充群組就是主要群組 | |
| -f | 把 -f 傳給 shell,是 csh 或 tcsh 使用的選項 | |
| -P | 建立新的虛擬終端機,不與原本的工作階段共用終端機 | |
| --session-command 指令 | 與 -c 相同但不建立新的工作階段,手冊不建議使用 |
🔲 su 指令模擬器
下面的模擬器從一般帳號 user1 開始,可以自己輸入 su、[su -]、sudo,再用 exit 返回,親自確認整個流程。帳號和密碼都是範例值。
4️⃣ sudo su 與 sudo -i 的差異
sudo su 是用 sudo 以 root 權限執行 su 的形式。因為 su 由 root 執行,所以不會詢問 root 密碼,而是在那之前由 sudo 詢問執行者的密碼(依官方文件)。
可以執行 sudo 的帳號由 /etc/sudoers 設定決定。未獲允許的帳號執行 sudo 時,會以 [user1 is not in the sudoers file.] 拒絕(依程式內的訊息)。
開啟 root shell 的各個指令所詢問的密碼與工作資料夾如下。本章的指令沒有在正式運作的伺服器上執行,而是依 su(1) 與 sudo(8) 手冊整理。
| 指令 | 詢問的密碼 | 執行的 shell | 工作資料夾 |
|---|---|---|---|
| su | root | root shell | 不變 |
| su - | root | root 登入 shell | /root |
| sudo su | 執行的帳號 | root shell | 不變 |
| sudo su - | 執行的帳號 | root 登入 shell | /root |
| sudo -i | 執行的帳號 | root 登入 shell | /root |
| sudo -s | 執行的帳號 | SHELL 變數的 shell(root 權限) | 不變 |
[sudo -i] 和 [sudo su -] 最後都會成為 root 登入 shell。[sudo -i] 由 sudo 直接把 root 的 shell 當成登入 shell 執行,[sudo su -] 則在中間再經過一次 su。
[sudo -s] 以 root 權限執行 SHELL 變數的 shell,不會移到家目錄。sudo 在密碼正確輸入一次後,預設 5 分鐘內在同一個終端機不會再詢問(依 sudoers 手冊)。
su 與 sudo 的差異,就像借用別人家的鑰匙和在管理室登記名字後進出的差異。
5️⃣ su 指令錯誤
切換到無法登入的帳號時,會以 nologin 代替 shell 執行,並出現 [This account is currently not available.]。在 root 執行 [su daemon] 時只出現這一行,結束代碼為 1。
su daemonThis account is currently not available.這段訊息由寫在帳號那一行最後一欄的 nologin 程式輸出,也在伺服器的 /usr/sbin/nologin 中找到了相同的文字。如果是 root,可以用 -s 指定 shell,再以該帳號執行指令。
密碼不對時會出現 [su: Authentication failure]。這段文字是 PAM 函式庫在驗證失敗時傳回的訊息。依官方手冊,su 在執行指令前失敗時,結束代碼為 1。
明明正確輸入了自己帳號的密碼 su 卻拒絕時,先確認那裡要輸入的是不是目標帳號的密碼。因為 sudo 詢問的是執行者的密碼,su 詢問的則是要切換過去的帳號的密碼。
寫了不存在的帳號名稱時,會出現 [su: user user9 does not exist or the user entry does not contain all the required fields](依程式內的訊息)。各錯誤的原因與要確認的事項如下。
| 輸出 | 原因 | 要確認的事項 |
|---|---|---|
| This account is currently not available. | 目標帳號的 shell 是 nologin | getent passwd 帳號那一行的最後一欄、root 可用 -s 指定 shell |
| su: Authentication failure | 密碼不對 | 是不是目標帳號的密碼(sudo 是你自己的密碼) |
| su: user user9 does not exist … | 沒有這個名稱的帳號 | getent passwd 帳號名稱 |
| user1 is not in the sudoers file. | 未允許使用 sudo 的帳號 | sudoers 設定與 wheel 群組 |
🔢 FAQ & 推薦內容
ℹ️ 聯盟行銷說明
本站內容包含聯盟行銷連結。訪客透過這些連結購買商品或服務時,本站會從賣家獲得佣金。在這個過程中,購買者支付的金額(遇到活動折扣時金額會降低↓)並不會因此提高。刊登的價格、折扣與庫存資訊以撰寫當時為準,可能與實際情況不同,購買前請向賣家做最後確認。商品的挑選與評價依本站自訂的標準撰寫,是否支付佣金不會影響介紹順序或評價內容。