翻譯自:https://www.howtoforge.com/tutorial/sudo-beginners-guide/
前奏在 Linux 命令行上工作時是否遇到過「權限被拒絕」錯誤?可能是您試圖執行需要 root 權限的操作。例如,以下屏幕截圖顯示了當我嘗試將二進位文件複製到系統目錄之一時引發的錯誤。
那麼這個問題的解決方案是什麼?很簡單,使用sudo命令。
使用 sudo 運行命令運行該命令的用戶將被提示輸入他們的登錄密碼。一旦輸入正確的密碼,操作將成功執行。
雖然 sudo 無疑是在 Linux 中使用命令行的任何人都必須知道的命令,但為了更負責任和有效地使用該命令,您還應該了解其他幾個相關(和深入)的細節。這正是我們將在本文中討論的內容。
什麼是sudosudo 表示 「superuser do」, 它允許已驗證的用戶以其他用戶的身份來運行命令。什麼是已驗證的用戶?現在大家可能不理解,簡單說就是我們可以通過自己設定的安全策略來給該用戶授權,未經授權的用戶沒法使用sudo命令。
大家可能會問,為啥我沒有給我的linux用戶授權,照樣也能使用sudo?這是因為你這個用戶肯定是在安裝系統的時候創建的,系統已經幫你添加了sudo授權。你可以試下使用useradd命令創建用戶,這些用戶默認沒有sudo權限。
sudo 命令與安全策略配合使用,默認安全策略是 sudoers,它通過文件 /etc/sudoers來配置。sudo支持插件式的安裝策略和輸入輸出日誌記錄架構,第三方可以為sudo開發和分發他們自己的安全策略作為插件。
安全策略確定用戶擁有哪些特權(如果有)運行sudo。該策略可能要求用戶進行自我身份認證,使用密碼或其他身份驗證機制。如果需要身份驗證,如果用戶的密碼未在可配置的時間限制內輸入,sudo將退出。這個限制由具體的安全策略指定;sudoers安全策略默認密碼提示超時是 5 分鐘。
安全策略可能支持憑據緩存,以允許用戶一段時間內再次運行sudo不需要驗證。默認情況下,sudoers策略緩存憑據在每個終端的上是 5 分鐘。有關更多信息,請參閱sudoers(5) 中的timestamp_type,timestamp_timeout選項。
內置命令行為sudo 的一個限制是 —— 它無法使用 Shell 的內置命令。例如, history 記錄是內置命令,如果你試圖用 sudo 執行這個命令,那麼會提示如下的未找到命令的錯誤:
victory@ubuntu:~$ sudo history
sudo: history: command not found
victory@ubuntu:~$為了克服上述問題,我們可以訪問 root shell,並在那裡執行任何命令,包括 Shell 的內置命令。
要訪問 root shell, 執行下面的命令:
victory@ubuntu:~$ sudo bash
root@ubuntu:/home/victory# ls
Desktop Documents Downloads Music Pictures Public Templates Videos
root@ubuntu:/home/victory#執行完這個命令後——您將觀察到提示符變為井號(#)。
/etc/suderos文件這個文件可謂是sudo的基礎。它控制著誰可以使用sudo命令來獲得提升的權限。它通常位於/etc/sudoers。想編輯這個文件,最有效最安全的方式就是,使用visudo命令。理由:
這個命令會提升權限啟動vi編輯器,那樣你就能編輯並保存該文件。
它還會給sudoers文件上文件鎖,那樣別人無法編輯該文件。
一旦你完成了編輯工作,它會分析文件,查找有無語法錯誤。
所以編輯sudo文件要比僅僅使用任何文本編輯器來得安全得多。
有意思的是,該文件的權限即使是root用戶,也是只讀:
victory@ubuntu:~$ ls -al /etc/sudoers
-r--r 1 root root 819 Dec 31 07:29 /etc/sudoers該文件含有許多參數。你可以指定哪些用戶或哪些用戶組可以執行哪些命令。
先看下文件格式:
user host=(run_as) command
user表示被授權的用戶,也就是你希望獲得sudo權限的用戶。host表示允許哪些遠程登錄主機可以使用sudo,比如你可能從192.168.1.2的主機通過ssh登錄過來。來幾個示例:
username ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
test ALL=(ALL) NOPASSWD:/usr/sbin/adduser,/usr/sbin/useradd授權username用戶能以任何主機登錄,以任何用戶的身份運行任何命令。
授權wheel 用戶組能以任何主機登錄,以任何用戶的身份運行任何命令。
授權test 用戶能以任何主機登錄,以任何用戶的身份,無需密碼運行adduser、useradd 命令。
NOPASSWD是常用的標籤,表示執行命令時無需密碼驗證。sudoers文件的語法太多了,在這裡就不一一介紹了。
什麼是 sudo 會話?如果您經常使用 sudo 命令,我相信您已經觀察到,在您成功輸入一次密碼後,您可以運行多個 sudo 命令而不會提示輸入密碼。但過了一段時間,sudo 命令再次要求您輸入密碼。
此行為與您運行的 sudo 驅動命令的數量無關,而是取決於時間。是的,默認情況下,sudo 在用戶輸入一次後的 15 分鐘內不會要求輸入密碼。超過這 15 分鐘,系統將再次提示您輸入密碼。
但是,如果您願意,可以更改此行為。為此,請使用以下命令打開 /etc/sudoers 文件:
sudo visudo然後轉到以下行:
Defaults env_reset
環境變量重置並在行尾添加以下變量(下面以粗體突出顯示)
Defaults env_reset,timestamp_timeout=[新值][new-value] 欄位應替換為您希望 sudo 會話持續的分鐘數。例如,我使用了值 40。
如果您希望每次使用 sudo 命令時都提示輸入密碼,那麼在這種情況下,您可以將值「0」分配給該變量。對於那些希望他們的 sudo 會話永遠不會超時的人,您可以分配值「-1」。
請注意,強烈建議不要使用值為 '-1' 的 timestamp_timeout。
sudo密碼提示符正如您可能已經觀察到的那樣,每當 sudo 提示您輸入密碼並且您開始輸入密碼時,什麼都沒有顯示 - 甚至沒有星號,這通常是正常的。雖然這通常沒什麼大不了的,但有些用戶可能出於某種原因希望顯示星號。
好消息是這是可能的,而且很容易做到。您所要做的就是更改 /etc/sudoers 文件中的以下行:
默認值 env_reset到
默認值 env_reset,pwfeedback並保存文件。
現在,每當您輸入 sudo 密碼時,星號都會出現
顯示sudo密碼提示符與 su 的區別在 GNU/Linux 中,有兩種方式可以用提升的權限來運行命令:
su 表示 「switch user」。使用 su,我們可以切換到 root 用戶並且執行命令。但是這種方式存在一些缺點:
因為 root 用戶為超級用戶,我們不能授予受控的訪問權限。
sudo 以獨特的方式解決了這些問題。
首先,我們不需要妥協來分享 root 用戶的密碼。
普通用戶使用他們自己的密碼就可以用提升的權限來執行命令。
我們可以控制 sudo 用戶的訪問,這意味著我們可以限制用戶只執行某些命令。
除此之外,sudo 用戶的所有活動都會被記錄下來,因此我們可以隨時審查進行了哪些操作。在基於 Debian 的 GNU/Linux 中,所有活動都記錄在 /var/log/auth.log 文件中。
我嘗試執行了sudo ls命令,查看下/var/log/auth.log日誌:
Dec 31 06:02:41 ubuntu sudo: victory : TTY=pts/0 ; PWD=/home/victory ; USER=root ; COMMAND=list
一些重要的 sudo 命令行選項
Dec 31 06:04:14 ubuntu sudo: victory : TTY=pts/0 ; PWD=/home/victory ; USER=root ; COMMAND=/usr/bin/ls
Dec 31 06:04:14 ubuntu sudo: pam_unix(sudo:session): session opened for user root by (uid=0)
Dec 31 06:04:14 ubuntu sudo: pam_unix(sudo:session): session closed for user root除了 -u 命令行選項(我們已經在本教程開頭討論過)之外,還有一些其他重要的 sudo 命令行選項值得一提。在本節中,我們將討論其中的一些。
-u user
以user身份執行命令,不加這個的話,默認是以root用戶執行。
-S
讓sudo從標準輸入讀取密碼而不是從終端設備。
這個密碼在寫腳本時非常有用,我們可以在腳本裡echo密碼給sudo實現非交互執行:
echo "123456" | sudo ls-k 選項
考慮這樣一種情況:您在輸入密碼後剛剛運行了一個 sudo 驅動的命令。現在,如您所知,默認情況下 sudo 會話保持活動狀態 15 分鐘。假設在此會話期間,您必須授予某人訪問您的終端的權限,但您不希望他們能夠使用 sudo。你會怎麼做?
值得慶幸的是,存在一個命令行選項*-k*允許用戶撤銷 sudo 權限。以下是 sudo 手冊頁對該選項的說明:
-k, --reset-timestamp
在沒有命令的情況下使用時,使用戶的緩存憑據無效。換句話說,下次運行 sudo 時將需要密碼。此選項不需要密碼,添加此選項是為了允許用戶從 .logout 文件中撤銷 sudo 權限。
當與可能需要密碼的命令或選項結合使用時,此選項將導致 sudo 忽略用戶的緩存憑據。因此,sudo 將提示輸入密碼(如果安全策略需要密碼)並且不會更新用戶的緩存憑據。簡而言之,就是你使用sudo -k來執行命令時,每次都需要輸入密碼。
-K
作用和**-k**一樣,只不過它後面不能跟命令,也不能和其他選項使用。
-s 選項
有時您的工作可能需要您運行大量需要 root 權限的命令,並且您不想時不時地輸入 sudo 密碼。此外,您不希望通過更改 /etc/sudoers 文件來調整 sudo 會話超時限制。
在這種情況下,您可能需要使用sudo 命令的*-s*命令行選項。以下是 sudo 手冊頁的解釋:
-s, --shell
運行由 SHELL 環境變量指定的 shell(如果它已設置)或由調用用戶的密碼資料庫條目(/etc/passwd)指定的 shell。如果指定了命令,它將通過 shell 的 -c 選項傳遞給 shell 以執行。如果未指定命令,則執行交互式 shell。
所以基本上,這個命令行選項的作用是:
啟動一個新的 shell - 至於哪個 shell,引用 SHELL env 變量。如果 $SHELL 為空, 則會選擇*/etc/passwd*文件中定義的 shell 。如果您還將命令名稱與 -s 選項一起傳遞(例如:sudo -s whoami),那麼實際執行的命令是:sudo /bin/bash -c whoami。如果您不嘗試執行任何其他命令(也就是說,您只是嘗試運行sudo -s),那麼您將獲得一個具有 root 權限的交互式 shell。-i 選項
-i 選項類似於我們剛剛討論的 -s 選項。但是,存在一些差異。-i表示獲得一個login shell。什麼是loging shell?也就是你以某個用戶登錄時的那個shell環境。我們都知道,登錄shell時,.profile文件會被shell讀取。
如果不跟任何命令,就相當於獲得了一個登錄shell;跟了命令,相當於在登錄shell裡執行命令(shell -c command)。
victory@ubuntu:~$ sudo -i
root@ubuntu:~#-l選項
列出調用該命令的用戶的sudo權限,還可以通過-U選項查看指定用戶的sudo權限:
victory@ubuntu:~$ sudo -ll
Matching Defaults entries for victory on ubuntu:
env_reset, pwfeedback, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User victory may run the following commands on ubuntu:
Sudoers entry:
RunAsUsers: ALL
RunAsGroups: ALL
Commands:
ALL
victory@ubuntu:~$ sudo -l
Matching Defaults entries for victory on ubuntu:
env_reset, pwfeedback, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User victory may run the following commands on ubuntu:
(ALL : ALL) ALLtest用戶是我通過useradd命令創建的用戶,所以它沒有任何sudo權限;而victory用戶是安裝系統時添加的,它可以 以任何用戶、從任何主機登錄、任何組,執行任何命令。
-v選項
對於sudoer策略,刷新緩存憑據,也就是密碼認證存活時間又延長了15分鐘。
補充前面提到,安裝系統時創建的用戶,默認就有sudo權限。看下配置就知道了:
victory@ubuntu:~$ sudo cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset,pwfeedback
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# 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
test ALL=(ALL) NOPASSWD:/usr/sbin/adduser,/bin/ls
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.dsudoers文件默認添加了三行:
root用戶、admini組、sudo組具有全部sudo權限。而我的用戶被添加到了sudo組中:
victory@ubuntu:~$ groups
victory adm cdrom sudo dip plugdev lpadmin lxd sambashare自然就有所有sudo權限了,換句話說,想簡單的給某個用戶添加sudo權限,將其添加到sudo組是個最便捷的方法。
結論我希望現在您至少已經了解了 sudo 背後的基本思想,以及如何調整它的默認行為。