# Linux (六) - 使用者和群組管理
在 [Linux (一) - 基本概念與系統操作](https://tienyulin.github.io/linux-basic-concept-command/) 中,我們有介紹到 Linux 其中一個很大的優勢就是可以讓多使用者多工進行操作,而使用者要使用系統的資源時,都需要先向系統管理員 (root) 申請帳號,再以這個帳號進入系統。
當然要做為 Linux 的系統管理員的話,也必須要很清楚如何管理帳號,所以這篇就是要來介紹如何管裡 Linux 系統的帳號。
<!-- more -->
## 帳號
對 Linux 系統來說,他並不認識你的帳號名稱,雖然登入的時候都是輸入帳號,但是那只是讓我們容易記住。Linux 系統只認得 `ID`,而 `ID` 和帳號之間的對應就存在 `etc/passwd` 中。如果你對於 `etc` 這個目錄還不清楚的話可以參考 [Linux (二) - 檔案系統架構](https://tienyulin.github.io/linux-filesystem/#etc) 中有簡單的做介紹。
以下會介紹幾個檔案都需要 `root` 的權限,所以在存取時要先取得 `root` 的權限。
### /etc/passwd
下面我們列出 `/etc/passwd` 來看一下 :
```bash=
$ cat etc/passwd
root:x:0:0:root:/root:/bin/bash
...略...
tony:x:1000:1000::/home/tony:/bin/bash
simon:x:1001:1001::/home/simon:/bin/bash
```
上面的輸出可以看到每個帳號一行資料,每一行以 `:` 隔開每個欄位。欄位依序是 :
* Username : 使用者登入的帳號名稱,最多 32 個字元。
* Password : 密碼會以 X 代替已經加密過的密碼,而加密的密碼會儲存在 `/etc/shadow`。
* UserID (UID) : 每一個帳號會有自己獨立的 `UID`,`0` 是 `root`,`1~99` 預留給系統的帳號。
* GroupID (GID) : 每一個帳號都會有一個對應的群組,所以也會有對應的 ID,而 `GID` 會對應到 `/etc/group` 中的 `group ID`。
* UserID Info : 可以加入一些額外的資訊,但不是必要的內容,所以可以看到上方 `tony` 和 `simon` 兩個帳號在這個欄位就是空的。
* Home Directory : 顯示帳號的家目錄位置,預設都是在 `/home` 目錄下會以帳號名稱建立一個目錄即為該帳號的家目錄。
* Shell : 顯示出帳號使用的 Shell。
### /etc/shadow
前面提到了加密的密碼會儲存在 `/etc/shadow` 中,下面我們先列出 `/etc/shadow` 來看一下 :
```bash=
$ cat /etc/shadow
root:locked::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
...略...
tony:!!:18535:0:99999:7:::
simon:!!:18543:0:99999:7:::
```
上面的輸出同樣以 `:` 隔開每個欄位,並且每一行是一個帳號的資訊。而欄位依序是 :
* Username : 帳號名稱。
* Encrypted Password : 這個欄位是加密過的密碼,如果這個欄位的第一個字元是 `!` 則代表密碼目前已經被鎖定無法登入。而如果是空的代表使用者不需密碼即可登入。
* Modified Date : 前一次變更密碼的日期,如果欄位數值為 0,則使用者下次登入時必須立即變更。如果是空的則代表密碼的使用期限和變更間隔時間被停用,也就是說密碼不會過期也可以隨意變更。
* Minimum Password Age : 密碼最短使用期限,指定兩次變更密碼最短必須要間隔多久,也就是說當密碼變更後,要多久才能再變更,以天為單位。
* Maximum Password Age : 密碼最長使用期限,指定一組密碼最長可以用多久,時間到就要更改,以天為單位。
* Password Expiration Warning Period : 密碼過期的警告期限,設定在密碼過期前多久要對使用者提出警告訊息,以天為單位。
* Password Inactivity Period : 密碼暫停使用的期間,當密碼過期時讓使用者還有多久的時間可以登入更改密碼,以天為單位。
* Account Experiation Date : 帳號過期時間,當時間到了就不能再登入,填入 0 可以讓帳號失效。
* Reserved Field : 最後一個欄位是保留欄位,目前沒有用途
以上的欄位如果為0或空,則代表停用此功能。
#### 重設密碼
由於加密過後的密碼基本上是沒有辦法被轉回明碼的,但是仍有機會被破解。
**一般的使用者**
一般使用者忘記了密碼可以透過系統管理員以 `root` 的身分使用 `passwd` 指令就可以重新設定了。
**root 忘記密碼**
root 忘記密碼會較麻煩,因為已經無法使用 root 登入了,所以可以透過重新開機進入單人維護模式,系統會給予 root 的權限,此時可以再以 `passwd` 指令修改。或是以 `LiveCD` 開機後掛載根目錄去修改 `/etc/shadow`,將 root 的密碼欄位清空。接著再重新開機即可不需要使用密碼,但是登入後要盡快去重設密碼。操作方式請參考以下幾篇 :
* [linux修改root密碼和linux忘記root密碼後找回密碼的方法](https://codertw.com/%E4%BC%BA%E6%9C%8D%E5%99%A8/381849/)。
* [忘記 root 密碼的解決之道](http://linux.vbird.org/linux_basic/0510osloader.php#solution_root)
### 列出帳號資訊
如果想要查看特定帳號的資訊,可以直接使用 `id` 指令。
```bash=
id [username]
```
**範例**
下面這個範例可以看到指定了特定的帳號後會輸出這個帳號的 `uid`、`gid`、`groups`。這裡可以和前面的 `/etc/passwd` 對照一下,可以看到帳號名稱是 `tony` 的 `uid` 都是 `1000`。這裡也要注意不要任意去修改 `etc/passwd` 的內容,不然會造成系統對應異常導致系統運作不正常。
另外也可以用於查詢帳號是否存在,若不存在也會回應沒有這個使用者。
```bash=
$ id tony
uid=1000(tony) gid=1000(tony) groups=1000(tony),0(root)
$ id frank
id: frank: no such user
```
## 群組
前面有提到每個帳號會對應到一個群組,下面我們就來介紹群組的相關設定和操作。
### /etc/group
群組的相關資訊就儲存在 `/etc/group`。下面我們列出 `/etc/group` 來看一下 :
```bash=
$ cat /etc/group
root:x:0:
bin:x:1:
daemon:x:2:
...略...
tony:x:1000:
simon:x:1001:
```
輸出同樣是以 `:` 隔開每個欄位,且每一行是一個群組的資訊。而欄位依序是 :
* Groupname : 群組名稱,是用於給使用者分辨的,對 Linux 系統來說只認得第三個欄位的 GID。
* Group Password : 群組密碼,同樣的密碼已經使用 `x` 來顯示,而加密過的密碼會在 `/etc/gshadow` 中。
* GID : 群組的 ID,前面介紹的 `/etc/passwd` 中的 GID 就是對應到此。
* User in group : 群組內的成員,如果要將使用者加入群組可以加在這個欄位。
**範例**
這個範例要將使用者直接透過 `/etc/group` 加入群組,首先使用 `vi` 編輯器打開 `/etc/group` 之後,將 `root:x:0:` 後面加上要加入的使用者,也就是上面介紹的群組內成員的欄位。如下 :
```bash=
$ vi /etc/group
root:x:0:tony,simon
bin:x:1:
daemon:x:2:
...略...
tony:x:1000:
simon:x:1001:
```
加進 `root` 群組後可以用 `id` 這個指令列出帳號的資訊來看。可以看到 `groups` 的地方會發現 `tony` 和 `simon` 都多了 `0(root)`,也就代表他們都已經被加進了 `root` 的群組。
```bash=
$ id tony
uid=1000(tony) gid=1000(tony) groups=1000(tony),0(root)
$ id simon
uid=1001(simon) gid=1001(simon) groups=1001(simon),0(root)
```
以上這個範例盡量不要將使用者加入 `root` 群組,因為這樣會讓使用者可以直接存取 `root` 群組的檔案。如果要使用也要在練習完後將 `root` 群組的使用者移除。
### 群組類別
#### 初始群組
上面的範例一直都有出現每個使用者對應到一個以使用者自己的名稱為名的群組,這個就是所謂的初始群組。而使用者一登入系統後就會馬上擁有初始群組的權限,所以可以在往回看到上一個範例,`tony` 和 `simon` 這兩個就是初始群組,並不需要在後面加上使用者自己的名稱。對應到 `/etc/passwd` 就是 `GID` 這個欄位。
#### 有效群組
在上一個範例中,我們將 `tony` 和 `simon` 加入了 `root` 的群組,因此 `tony` 和 `simon` 就有權限可以存取 `root` 群組的檔案。但是如果現在要建立一個檔案,這個檔案會屬於哪個群組呢 ? 當然就是有效群組。
##### groups
可以透過 `groups` 指令來查看目前登入的帳號有哪些群組的權限,而第一個即為有效群組,剩下的稱為 `支援群組`。
**範例**
```bash=
simon@mycomputer$ groups
simon tony
```
以上面這個例子來說也就是 simon 的有效群組是 `simon`,而支援群組是 `tony`。所以如果現在建立一個檔案,則檔案就會屬於 `simon` 這個群組。如下 :
```bash=
$ touch test.txt
$ ls -l test.txt
-rw-rw-r-- 1 simon simon 11 Oct 14 06:20 test.txt
```
##### newgrp
如果想要切換有效群組,可以透過 `newgrp` 指令來切換。但前提是要切換的群組必須要是支援群組。
**範例**
首先先將 `simon` 的有效群組換成 `tony`,接著使用 `groups` 指令就可以看到輸出的第一個群組是 `tony`,也就代表有效群組被換成了 `tony`。這時再次新增一個檔案並且查看檔案的詳細資訊可以看到檔案所屬的群組被換成了 `tony`。
```bash=
simon@mycomputer$ newgrp tony
simon@mycomputer$ groups
tony simon
simon@mycomputer$ touch test2.txt
simon@mycomputer$ ls -l test2.txt
-rw-r--r-- 1 simon tony 0 Oct 14 06:32 test2.txt
```
## 使用者帳號管理
系統管理員可以新增、修改和刪除使用者的帳號。下面我們就來介紹如何管理使用者帳號。
### 新增使用者 (useradd)
加入新的使用者的帳號可以使用 `useradd` 指令,但是要注意的是 `useradd` 新增完帳號之後不是就可以馬上使用了,還需要再透過 `passwd` 設定密碼才可以使用。
```bash=
useradd [option] [username]
```
option :
* -u : 直接指定一組 UID 給這個帳號。也就是 [/etc/passwd](#/etc/passwd) 第三欄的 `UserID`。
* -g : 指定群組名稱,這裡指定的群組就是 `初始群組`。
* -c : 加入帳號的說明,也就是 [/etc/passwd](#/etc/passwd) 第五欄的 `UserID Info`。
* -d : 指定某個目錄成為家目錄,而不使用預設目錄。也就是 [/etc/passwd](#/etc/passwd) 第六欄的 `Home Directory`。
* -s : 指定一個 Shell,預設是 `/bin/bash`。也就是 [/etc/passwd](#/etc/passwd) 第七欄的 `Shell `。
* -e : 指定一個日期,格式為 `YYYY-MM-DD`,用來表示帳號失效的日期。也就是 [/etc/shadow](#/etc/shadow) 第八欄的 `Account Experiation Date`。
* -f : 指定密碼是否會失效,0 為立即失效,-1 則永遠不失效 (會過期而需重新設定)。也就是 [/etc/shadow](#/etc/shadow) 第七欄的 `Password Inactivity Period`。
**範例**
下面這個範例新增一個帳號 `biden`,並且針對這個帳號做一些設定。
```bash=
$ useradd -u 7788 \
-g tony \
-c "biden is a dumb dumb." \
-d /home \
-s /bin/sh \
-e 2020-10-14 \
-f 180 \
biden
```
由下面的輸出可以看到新增完此帳號後,設定的內容都有寫進對應的欄位中。
```bash=
$ cat /etc/passwd
...略...
biden:x:7788:1000:biden is a dumb dumb.:/home:/bin/sh
$ cat /etc/shadow
...略...
biden:!!:18549:0:99999:7:180:18549:
$ id biden
uid=7788(biden) gid=1000(tony) groups=1000(tony)
```
### 修改密碼 (passwd)
預設使用 `useradd` 建立帳號後,這個帳號會暫時先被鎖住不能登入。可以看到前一個範例的 `cat /etc/shadow` 的輸出,在第二個欄位顯示 `!!`。在 [/etc/shadow](#/etc/shadow) 中我們有說過如果這個欄位的第一個字是 `!` 代表被鎖定不能登入。所以這個時候就需要用 `passwd` 指令來設定密碼。
除了建立帳號時要使用 `passwd` 來設定密碼,平常如果忘記密碼也可以使用 `passwd` 來重設密碼。
```bash=
passwd [option] [user name]
```
option :
* -d : 刪除密碼 (delete)。
* -l : 將使用者的密碼鎖定 (lock),會在 [/etc/shadow](#/etc/shadow) 的第二個欄位加上 `!`。
* -u : 將使用者的密碼解除鎖定 (unlock)
* -e : 將使用者的密碼設為過期 (expire),會更改 [/etc/shadow](#/etc/shadow) 的第三個欄位,也就是使用者下次登入一定要改密碼。
* -f : 強制執行。
* -x : 設定密碼的最長使用期限 (max),以天為單位,會更改 [/etc/shadow](#/etc/shadow) 的第五個欄位。
* -n : 設定密碼的最短使用期限 (min),也就是多久後才可以改密碼,以天為單位,會更改 [/etc/shadow](#/etc/shadow) 的第四個欄位。
* -w : 設定密碼過期前幾天會發出警告 (warning),會更改 [/etc/shadow](#/etc/shadow) 的第六個欄位。
* -i : 設定密碼過期幾天內還可以讓使用者登入修改密碼 (inactive),會更改 [/etc/shadow](#/etc/shadow) 的第七個欄位。
* -S : 列出使用者目前帳戶的資訊 (status)。
* `--stdin` : 透過前一個 pipline 的輸出作為密碼輸入,可用於 `Shell Script`。
以上這些指令除了 `-f` 以外其他都需要 `root` 的權限。
user name : 如果沒有指定帳號就是更改目前的帳號,所以這裡要注意如果在 root 的時候要記得加上要改的帳號,不然就會改到 root。
👁🗨 如果是要更改自己的密碼就可以直接下 `passwd` 就可以更改了,不過就只能改自己的,如果是忘記密碼了或是要更改他人的密碼都需要 `root` 才能更改。
**範例**
首先就先將剛剛建立的 `biden` 加上密碼,改完後可以看到 `/etc/shadow` 的第二個欄位已經不是 `!!`,代表現在是有密碼可以登入的。
```bash=
$ passwd biden
Changing password for user biden.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
$ cat /etc/shadow
...略...
biden:$6$5ksojzZi$a9228NCaylRTaecg1qgZAhk0.lXLA5aZfehUhIncb7pceRgrOl3eBgZqxF1CX9rOwj0H0wF111AfHWRxskdsf/:18549:0:99999:7:180:18549:
```
將 `biden` 的密碼刪除,刪除完成後可以看到第二個欄位密碼變成空的。這也是一個方法讓使用者忘記密碼時可以刪掉他的密碼讓他自己重新設定。
```bash=
$ passwd -d biden
Removing password for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::18549:0:99999:7:180:18549:
```
將 `biden` 的密碼鎖住,可以看到第二個欄位又變成了 `!!`,也就代表不能登入了。
```bash=
$ passwd -l biden
Locking password for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden:!!:18549:0:99999:7:180:18549:
```
將 `biden` 的密碼解鎖,讓他可以重新登入,不過這裡有一個很有趣的地方是上鎖再解鎖之後並不是回復成原來的密碼,而是變成沒有密碼可以直接登入。
```bash=
$ passwd -u biden
Unlocking password for user biden.
passwd: Warning: unlocked password would be empty.
passwd: Unsafe operation (use -f to force)
$ passwd -uf biden
Unlocking password for user biden.
passwd: Success
$ cat /etc/shadow
biden::18549:0:99999:7:180:18549:
```
將 `biden` 設為密碼過期,下次登入一定要重設密碼,設定完成後可以看到 `/etc/shadow` 的第三個欄位變成 0。
```bash=
$ passwd -e biden
Expiring password for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::0:0:99999:7:180:18549:
```
將 `biden` 的帳號最長使用期限設為 10 天,可以看到在設定天數的這些 option 是將天數直接寫在 option 後面,下面其他 option 也是同樣的方式。設定完成後可以看到 `/etc/shadow` 的第五個欄位被改成了 10。
```bash=
$ passwd -x 10 biden
Adjusting aging data for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::0:0:10:7:180:18549:
```
將 `biden` 的帳號最短使用期限設為 3 天,這裡的最短是指要過多久才可以更改。設定完成後可以看到 `/etc/shadow` 的第四個欄位被改成了 3。
```bash=
$ passwd -n 3 biden
Adjusting aging data for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::0:3:10:7:180:18549:
```
將 `biden` 的帳號使用到期警告設為 5 天前,這裡的最短是指要過多久才可以更改。設定完成後可以看到 `/etc/shadow` 的第六個欄位被改成了 5。
```bash=
$ passwd -w 5 biden
Adjusting aging data for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::0:3:10:5:180:18549:
```
將 `biden` 的帳號使用到期後還可以登入修改密碼的期限設為 7 天。設定完成後可以看到 `/etc/shadow` 的第七個欄位被改成了 7。
```bash=
$ passwd -i 7 biden
Adjusting aging data for user biden.
passwd: Success
$ cat /etc/shadow
...略...
biden::0:3:10:5:7:18549:
```
如果想簡單的看使用者的帳戶資訊,可以使用 `-S` 直接列出來,前面的範例是為了要清楚的知道到底是改到哪裡的設定。如下 :
```bash=
$ passwd -S biden
biden NP 1970-01-01 3 10 5 7 (Empty password.)
```
接著我們練習一組用 `root` 建立好帳號之後再切到使用者下再次修改密碼,如下 :
```bash=
root@mycomputer$ useradd gina
root@mycomputer$ passwd gina
Changing password for user gina.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
root@mycomputer$ su gina
gina@mycomputer$ passwd
Changing password for user gina.
Changing password for gina.
(current) UNIX password:
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```
最後,我們用 `--stdin` 來直接一次完成設定密碼。前面的 `echo` 指令會印出要設定的密碼,而後面的 `passwd` 就會使用 `echo` 指令的輸出直接輸入作為密碼,如此就不需要再輸入密碼即可完成密碼設定。
```bash=
$ echo "1q2w3e4r5t_" | passwd --stdin gina
Changing password for user gina.
passwd: all authentication tokens updated successfully.
```
上述這種做法通常都用於 `Shell Script`,可以一次大量建立使用者的帳號。但是如果用 `Shell Script` 會有個缺點是密碼保留在指令中,駭客可以透過 `/root/.bash_history` 取得命令的歷史紀錄並獲得密碼。
### 密碼時效管理(chage)
除了使用 `passwd` 指令來修改密碼的設定外,還可以用 `chage` 指令來更改。`chage` 就是 `change age`,可以用來修改密碼各種時間的設定。
```bash=
chage [option] [user name]
```
option :
-l : 列出此帳號的詳細密碼時效資訊。
-d : 上一次變更密碼的日期,填入格式為 `YYYY-MM-DD`,若填入 0 則下次登入強制必須更改密碼,會更改 [/etc/shadow](#/etc/shadow) 的第三個欄位。
-m : 密碼最短使用期限,填入天數,會更改 [/etc/shadow](#/etc/shadow) 的第四個欄位。
-M : 密碼最長使用期限,填入天數,會更改 [/etc/shadow](#/etc/shadow) 的第五個欄位。
-W : 密碼過期前幾天會發出警告,填入天數,會更改 [/etc/shadow](#/etc/shadow) 的第六個欄位。
-I : 密碼過期幾天內還可以登入修改密碼,填入天數,會更改 [/etc/shadow](#/etc/shadow) 的第七個欄位。
-E : 帳號失效日期,時間到就不能再登入,填入格式為 `YYYY-MM-DD`,會更改 [/etc/shadow](#/etc/shadow) 的第八個欄位。
**範例**
我們先用 `-l` 將帳號的密碼時效設定列出來看一下,如下 :
```bash=
$ chage -l biden
Last password change : password must be changed
Password expires : password must be changed
Password inactive : password must be changed
Account expires : Oct 14, 2020
Minimum number of days between password change : 3
Maximum number of days between password change : 10
Number of days of warning before password expires : 5
```
接著我們來對這些設定進行更改,但是我們更改的時候不加 `option`。`chage` 預設如果不加 `option` 的話就會一個一個列出來讓你改,不想改的欄位就按 `Enter` 就可以跳過,如下 :
```bash=
$ chage biden
Changing the aging information for biden
Enter the new value, or press ENTER for the default
Minimum Password Age [3]:
Maximum Password Age [10]: 15
Last Password Change (YYYY-MM-DD) [1970-01-01]: 2020-10-15
Password Expiration Warning [5]:
Password Inactive [7]:
Account Expiration Date (YYYY-MM-DD) [2020-10-14]: 2021-10-15
$ chage -l biden
Last password change : Oct 15, 2020
Password expires : Oct 30, 2020
Password inactive : Nov 06, 2020
Account expires : Oct 15, 2021
Minimum number of days between password change : 3
Maximum number of days between password change : 15
Number of days of warning before password expires : 5
```
不過這種做法通常還是用在手動設定,如果要用 `Shell Script` 大量設定的話還是用 `option` 會比較方便。
### 帳號資料修正 (usermod)
如果在 `useradd` 的時候加入了錯誤的資料,可以直接去 `/etc/passwd` 和 `/etc/shadow` 修改,不過 Linux 也有提供指令可以直接修改。
```bash=
usermod [option] [user name]
```
option :
* -c : 帳號的說明,會修改 [/etc/passwd](#/etc/passwd) 的第五欄。
* -d : 帳號的家目錄,會修改 [/etc/passwd](#/etc/passwd) 的第六欄。
* -e : 帳號失效日期,時間到就不能再登入,填入格式為 `YYYY-MM-DD`,會更改 [/etc/shadow](#/etc/shadow) 的第八個欄位。
* -f : 密碼過期幾天內還可以登入修改密碼,填入天數,會更改 [/etc/shadow](#/etc/shadow) 的第七個欄位。
* -g : 修改初始群組,填入 GID,會修改 [/etc/passwd](#/etc/passwd) 的第四欄。
* -G : 修改支援群組,會修改 [/etc/group](#/etc/group) 的第四欄。
* -a : 增加支援群組,與 `-G` 搭配使用,會修改 [/etc/group](#/etc/group) 的第四欄。
* -l : 修改帳號名稱,會修改 [/etc/passwd](#/etc/passwd) 的第一欄。
* -s : 修改 Shell,會修改 [/etc/passwd](#/etc/passwd) 的第七欄。
* -u : 修改 UID,會修改 [/etc/passwd](#/etc/passwd) 的第三欄。
* -L : 暫時鎖住使用者的密碼,會修改 [/etc/shadow](#/etc/shadow) 的第二欄。等於 `passwd -l`。
* -U : 解鎖使用者的密碼,相對於 `-L`,會修改 [/etc/shadow](#/etc/shadow) 的第二欄。等於 `passwd -u`。
**範例**
首先先針對幾個比較簡單的欄位做修改,結果如下 :
```bash=
$ usermod -c "will biden beat trump ?" -e 2021-05-08 -f 120 biden
$ cat /etc/passwd
...略...
biden:x:7788:1000:will biden beat trump ?:/home:/bin/bash
$ cat /etc/shadow
...略...
biden::18550:3:15:5:120:18755:
```
下面這個範例主要示範群組的修改,首先更改初始群組這個這個比較沒有問題,接著修改支援群組要特別注意,可以看到修改成 `simon` 後是直接覆蓋過去不是加上去。要加支援群組要使用 `-aG` 才能新增。
```bash=
# 修改初始群組
$ usermod -g gina biden
$ id biden
uid=7788(biden) gid=7789(gina) groups=7789(gina)
# 修改支援群組
$ usermod -G tony biden
$ id biden
uid=7788(biden) gid=7789(gina) groups=7789(gina),1000(tony)
# 修改支援群組
$ usermod -G simon biden
$ id biden
uid=7788(biden) gid=7789(gina) groups=7789(gina),1001(simon)
# 增加支援群組
$ usermod -aG tony biden
$ id biden
uid=7788(biden) gid=7789(gina) groups=7789(gina),1000(tony),1001(simon)
```
接著我們用 `-l` 將使用者的帳號名稱做修改,下面這個範例可以看到 `biden` 被改成 `biden2` 之後就找不到 `biden` 了。不過這裡也可以觀察到改名過後的 `biden2` 的 `UID` 還是 `7788`,這也證實了前面提到的 Linux 系統只認得 `UID` 並不認得使用者名稱。
```bash=
$ usermod -l biden2 biden
$ id biden
id: biden: no such user
$ id biden2
uid=7788(biden2) gid=7789(gina) groups=7789(gina),1000(tony),1001(simon)
```
而 `UID` 建議不要隨便更改,容易造成系統對應錯亂。
### 刪除使用者 (userdel)
刪除使用者會將使用者所有相關的資料都刪除,包含 :
* /etc/passwd : 帳號資訊
* /etc/shadow : 密碼資訊
* /etc/group : 群組資訊
* /etc/gshadow : 群組密碼資訊
* /home/[user name] : 家目錄,使用者的檔案
* /var/spool/mail/[user name] : 郵件
所以在刪除前需要確定是真的要`清除整個帳號的所有資料`還是只要`暫時性停用這個帳號`。如果只是要 `暫時停用帳號` 可以將 `/etc/shadow/` 的第八個欄位 (Account Experiation Date) 設為 0 就可以讓帳號不能使用。
```bash=
userdel [option] [user name]
```
option :
* -r : 連同使用者的家目錄一起刪除。
加了 `-r` 並不代表就可以完全刪除這個使用者所有建立的檔案,因為使用者可能會在家目錄以外的地方建立檔案。所以可以先用 `find` 指令找到該使用者擁有的所有檔案再進行刪除。
**範例**
這裡我們就將 `biden` 這個帳號刪除,如下 :
```bash=
$ userdel -r biden
$ id biden
id: biden: no such user
```
## 群組管理
群組也可以建立及刪除,甚至可以設定群組管理員來管理帳號的加入和移除。
### 建立群組 (groupadd)
建立群組可以使用 `groupadd` 指令來完成。
```bash=
groupadd [option] [group name]
```
option :
* -g : 指定特定的 GID。
* -p : 指定一組 `已加密` 的密碼,不過群組密碼並不常用。
**範例**
這個範例新增一個群組並且指定 GID 和密碼,由於密碼必須是加密的,所以可以使用 `openssl` 進行加密。如果沒有加密會在 `/etc/gshadow` 可以直接看到明碼。
```bash=
$ groupadd -g 8877 -p `openssl 1q2w3e4r5t_ -1` group4
```
### 修改群組 (groupmod)
groupmod 可以修改群組的 GID 或是群組名稱。
```bash=
groupmod [option] [group name]
```
option :
* -g : 修改 GID。
* -n : 修改群組名稱。
* -p : 修群組密碼,同樣需要加密。
**範例**
下面這個範例先新增一個群組並將群組 GID 和名稱都進行修改。不過 `GID` 建議還是不要亂改,會造成系統對應錯亂。
```bash=
$ groupadd -g 9100 group5
$ cat /etc/group
...略...
group5:x:9100:
$ groupmod -g 9200 -n group6 group5
$ cat /etc/group
...略...
group6:x:9200:
```
### 刪除群組 (groupdel)
刪除群組可以使用 `groupdel` 指令來完成。
```bash=
groupdel [group name]
```
**範例**
這個範例我們直接刪除剛剛改過名稱的 `group6`。不過可以看到再刪除另一個群組 `tony` 的時候會發現不能刪除,因為有帳號使用這個群組作為初始群組,如果刪掉的話會造成這個帳號登入後找不到 `GID`。如果一定要刪除要先到 `/etc/passwd` 中確定沒有帳號的 `GID` 使用這個群組作為初始群組。
```bash=
$ groupdel group6
$ groupdel tony
groupdel: cannot remove the primary group of user 'tony'
```
### 群組管理員 (gpasswd)
Linux 系統針對群組還有再開放一個群組管理員的功能,`root` 可以針對每一個群組指定群組的管理員,群組管理員可以決定要讓誰加入群組以及將誰移出群組。
```bash=
gpasswd [option] [group name]
```
option :
* -a : 加入使用者到群組。
* -d : 將使用者從群組中移除。
* -r : 刪除群組密碼。
* -R : 限制群組的存取權僅限群組成員。
* -M : 設定組員名單,格式為 `user1,user2,...`,可以一次指定多個。
* -A : 設定群組管理員,格式為 `admin1, admin2,...`,可以一次指定多個。
以上這些選項,`-M` 和 `-A` 只有 `root` 可以操作。
**範例**
這個範例首先先新增多個使用者來讓後面操作,然後新增一個群組並且給予密碼。接著 `root` 指定群組的管理員和群組的成員。
指定完群組管理員後,我們切換使用者到其中一個群組管理員 `tim`,接著 `tim` 就可以新增和刪除使用者了。
```bash=
# 新增帳號
$ useradd tim
$ useradd frank
$ useradd mary
$ useradd lin
$ useradd henry
# 新增群組並給予密碼
$ groupadd group10
$ gpasswd group10
Changing the password for group group10
New Password: 1q2w3e4r5t_
Re-enter new password: 1q2w3e4r5t_
# root 指定群組管理員&群組成員
$ gpasswd -A tim,frank -M mary,lin group10
$ cat /etc/group
...略...
group10:x:8867:mary,lin
# 切換到群組管理員 tim
$ su tim
# 加入 henry 到群組
$ gpasswd -a henry group10
Adding user henry to group group10
$ cat /etc/group
...略...
group10:x:8867:mary,lin,henry
# 將 mary 從群組移除
$ gpasswd -d mary group10
Removing user mary from group group10
$ cat /etc/group
...略...
group10:x:8867:lin,henry
```
## Summary
本篇介紹了非常多關於帳號和群組管理的方式,如果身為一個 Linux 的系統管理員那一定要熟悉上面這些設定的方法。
## 參考
[1] [/etc/passwd 檔案解讀](https://www.opencli.com/linux/etc-passwd)
[2] [Linux 帳號管理與 ACL 權限設定](http://linux.vbird.org/linux_basic/0410accountmanager.php)
[3] [Linux 新增使用者 useradd 指令用法教學與範例](https://blog.gtwang.org/linux/linux-useradd-command-tutorial-examples/)
[4] [Linux 的 /etc/shadow 檔案結構:儲存真實密碼的地方](https://blog.gtwang.org/linux/linux-etc-shadow-file-format/)
[5] [Linux useradd 命令介紹](https://kknews.cc/zh-tw/code/63y8n9l.html)
[6] [歷史命令](https://dywang.csie.cyut.edu.tw/dywang/linuxSystem/node89.html)
[7] [Linux Groups Can Have Paswords](https://digi.ninja/blog/group_password.php)
###### tags: `Linux`