Skip to main content

4.1. Users and Groups: User, group, environment profile và resource limit

Mục lục​


1. Vì sao mỗi người dùng cần một account riêng?​

Một Linux server có năm người dùng chung một account. Ai cũng đọc được file của người khác, ai cũng sửa được cấu hình editor của người khác, và khi có lệnh gõ sai làm mất dữ liệu thì không ai biết lệnh đó từ tay ai. Tách thành năm account riêng xử lý được cả ba chuyện đó cùng lúc.

Với người dùng, account riêng nghĩa là có file và directory cá nhân, được permission bảo vệ khỏi những người khác trên cùng máy, và được tự chọn setting cho những tool mình hay dùng.

Với người quản trị, account riêng mở ra khả năng giới hạn privilege theo đúng phạm vi công việc của từng người. Một người chỉ cần đọc log thì không cần quyền ghi vào /etc. Giới hạn đó thu nhỏ thiệt hại khi có ai gõ sai một lệnh, và nâng mức an toàn chung của hệ thống.

Phần việc còn lại thuộc về người quản trị: tạo, sửa, khóa và xóa những account đó khi nhân sự vào ra.


2. Tạo user mới và những gì diễn ra phía sau​

Lệnh thêm user mới tên đúng như chức năng của nó, adduser. Dạng gọn nhất chỉ cần tên account:

sudo adduser john

# Output (minh họa):
Adding user `john' ...
Adding new group `john' (1001) ...
Adding new user `john' (1001) with group `john' ...
Creating home directory `/home/john' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for john
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]

Chuỗi tương tác gồm ba chặng: nhập password rồi nhập lại lần nữa, điền vài thông tin về người dùng (họ tên đầy đủ, số điện thoại và tương tự), cuối cùng gõ y để xác nhận thông tin đã đúng và đồng ý tạo account. Phần thông tin ở giữa gần như luôn bỏ qua bằng cách bấm Enter cho từng dòng.

Chỉ một lệnh đó, nhưng hệ thống làm khá nhiều việc.

What one adduser call sets upsudo adduser johnone commandUser john is added to the systemGroup john is created automaticallyGroup john becomes his primary groupHome directory /home/john is createdLogin shell is set to /bin/bashFiles from /etc/skel are copied in

Diễn giải từng dòng trong hình:

  • User john được thêm vào hệ thống.
  • Một group mới cũng tên john được tạo tự động.
  • Group john được đặt làm primary group của user john.
  • Home directory được tạo tại /home/john, nơi john chứa file, subdirectory và setting chương trình của riêng mình.
  • Shell mặc định được đặt là chương trình ở /bin/bash. Mỗi lần john đăng nhập, toàn bộ session của anh ta chạy bên trong ứng dụng này.
  • Mọi file trong /etc/skel được copy vào /home/john.
  • Account được đặt là không bao giờ hết hạn.

Xem thử trong /etc/skel có gì:

ls -a /etc/skel

Đến đây john đã có account, nhưng chưa có password nên chưa đăng nhập được. Đặt password cho anh ta bằng:

sudo passwd john

Template cho user mới với etc skel​

Thư mục /etc/skel là chỗ đặt sẵn những file muốn mọi user tạo sau này đều có. Mỗi lần adduser chạy, toàn bộ nội dung của nó được copy sang home directory của account mới.

Một tình huống dùng được ngay: cần thông báo một quy định nội bộ cho mọi người mới vào. Người cũ đã biết quy định đó, còn mỗi người mới thì khả năng cao là chưa. Thêm một file vào /etc/skel giải quyết xong chuyện này:

sudo vi /etc/skel/README

Nội dung file, ví dụ:

Please don't run CPU-intensive processes between eight a.m. and ten p.m.

Lưu file, tạo một user mới để thử, rồi vào home directory của người đó mà xem:

ls -a

# Output (minh họa):
. .. .bash_logout .bashrc .profile README

Option -a làm ls liệt kê tất cả file, kể cả những file bị ẩn khỏi output mặc định. File có tên bắt đầu bằng dấu chấm, như .bashrc, chỉ hiện ra khi có -a. Trong danh sách trên, mọi file đều được copy từ /etc/skel, gồm cả README vừa thêm vào. User mới sẽ thấy nó khi xem home directory của mình, và đọc được nội dung bằng:

cat README

# Output:
Please don't run CPU-intensive processes between eight a.m. and ten p.m.

Xóa account và chọn shell hoặc home directory khác​

Khi cần xóa một account:

sudo deluser john

Lệnh này chỉ xóa đúng user account john. Group cùng tên john có thể bị gỡ theo nếu không còn thành viên nào khác thuộc group đó. Nhưng home directory /home/john vẫn còn nguyên, và đó là hành vi hợp lý: file cá nhân của anh ta có thể vẫn còn cần dùng. Khi đã chắc chắn những file đó không còn cần nữa, bảo deluser dọn luôn home directory cùng mail spool:

sudo deluser --remove-home john

Trở lại adduser, nếu các giá trị mặc định không phù hợp thì chọn shell và home directory khác ngay lúc tạo account:

sudo adduser --home /home/otherdirectory --shell /bin/sh john

Chỉ muốn đổi shell mà giữ vị trí home directory mặc định thì truyền option shell và bỏ option home directory đi:

sudo adduser --shell /bin/sh john

Quên option nào thì tra nhanh:

adduser --help

adduser hay useradd​

Khóa học dùng adduser xuyên suốt, và trên Ubuntu hay Debian thì đó là lựa chọn đúng. Nhưng adduser cùng deluser và addgroup là công cụ riêng của họ Debian: chúng là lớp vỏ bọc bên ngoài các công cụ cấp thấp useradd, groupadd và usermod, thêm vào phần hỏi đáp tương tác, cách chọn UID/GID theo Debian Policy, và việc copy /etc/skel sẵn. Trên Red Hat, CentOS hay Fedora không có adduser theo nghĩa đó, chỉ có bộ useradd / usermod / userdel của shadow-utils, và bộ này thì có mặt ở mọi bản phân phối.

Chi tiết này có giá trị thực tế với kỳ thi, vì từ 11/05/2023 đề LFCS không còn phụ thuộc distro. Gõ adduser trên một máy họ RHEL sẽ nhận về lệnh không tồn tại. Khi cần một lệnh chạy được ở mọi nơi thì dùng useradd, đổi lại phải tự chỉ định những thứ adduser vốn làm hộ:

sudo useradd --create-home --shell /bin/bash john
sudo useradd -m -s /bin/bash john

Thiếu -m thì useradd không tạo home directory, và đó là khác biệt gây bất ngờ nhiều nhất khi chuyển từ adduser sang.


3. Numeric ID, system account và các lệnh tra cứu danh tính​

Những chi tiết của account vừa tạo, gồm username, user ID, group ID, shell ưa dùng và home directory, đều được lưu ở /etc/passwd. Tên file dễ gây nhầm vì nghe như chỗ chứa password, thực tế nó chỉ chứa dữ liệu về account. Xem bằng:

cat /etc/passwd

# Output (rút gọn):
root:x:0:0:root:/root:/bin/bash
john:x:1001:1001::/home/john:/bin/bash
Fields of one line in /etc/passwdjohnusernamexpassword1001UID1001GIDemptycomment/home/johnhome dir/bin/bashlogin shellThe same line as the file stores itjohn❌1001:1001::/home/john:/bin/bashThe first 1001 is the user ID, the second is the primary group ID

Số 1001 đầu tiên là ID gắn với username john. Số 1001 thứ hai là ID số của primary group của anh ta, trong trường hợp này cũng là group tên john. Hai trường cuối là home directory và login shell ưa dùng.

adduser tự chọn ID số còn trống theo thứ tự tăng dần. User đầu tiên nhận ID 1000, user tiếp theo nhận 1001, và tiếp tục như vậy. Khi cần chỉ định một ID khác bằng tay:

sudo adduser --uid 1100 smith

User smith sẽ có ID số 1100, và group tên smith cũng nhận ID số 1100.

Xem ai sở hữu file và mình đang là ai​

Muốn biết username và group nào sở hữu file hay directory thì dùng ls -l như thường lệ. Muốn thấy ID số của user và group sở hữu thì thêm option -n:

ls -l
ls -ln

Có lúc cần biết chính account đang đăng nhập là ai. Lệnh này in username, các group mà account đó là thành viên, kèm ID số tương ứng:

id

# Output (minh họa):
uid=1001(john) gid=1001(john) groups=1001(john)

Chỉ cần đúng username thì gọn hơn:

whoami

# Output:
john

System account dành cho chương trình​

Ngoài user account cho người, còn một loại nữa gọi là system account. Tạo một system account tên sysacc bằng cách thêm option --system:

sudo adduser --system --no-create-home sysacc

Option --no-create-home bảo lệnh không tạo home directory, vì system account thường không cần tới. ID số của system account thường nhỏ hơn 1000, nên sysacc có thể nhận một ID như 114 hoặc 115.

Lý do tồn tại hai loại account này nằm ở đối tượng dùng chúng: user account dành cho người, system account dành cho chương trình. Daemon thường chạy dưới system account, chẳng hạn một daemon database server.

Nếu đang gõ theo trong máy ảo, dọn hai account vừa tạo trước khi sang phần sau.


4. Sửa account đang có bằng usermod​

Tạo lại user john để có cái mà sửa:

sudo adduser john

Giả sử sau đó cần đổi vài chi tiết của account này. Công cụ cho việc đó là usermod, viết tắt của user modify.

Đổi home directory của john:

sudo usermod --home /home/otherdirectory --move-home john
sudo usermod -d /home/otherdirectory -m john

Hai dòng trên tương đương nhau. Option --move-home bảo đảm directory cũ được di chuyển hay nói đúng hơn là đổi tên, nhờ vậy john vẫn truy cập được file cũ của mình. Trong ví dụ này, /home/john được đổi tên thành /home/otherdirectory.

Đổi username từ john sang jane:

sudo usermod --login jane john
sudo usermod -l jane john

Đổi login shell:

sudo usermod --shell /bin/othershell jane
sudo usermod -s /bin/othershell jane

Thứ tự tham số của usermod luôn là giá trị mới trước, tên account sau. Gõ ngược lại là sửa sai account hoặc báo lỗi không tìm thấy user.


5. Khóa account và hạn dùng của account với password​

Một người nghỉ việc tạm thời, hoặc một account bị nghi là đã lộ password. Chưa muốn xóa hẳn vì có thể cần mở lại, nhưng phải chặn đăng nhập ngay. Option --lock của usermod, viết tắt là -L, làm đúng việc đó:

sudo usermod --lock jane
sudo usermod -L jane

Account bị vô hiệu hóa nhưng không bị xóa. Người dùng không đăng nhập bằng password của mình được nữa. Nhưng họ vẫn có thể vào được bằng SSH key nếu phương thức đăng nhập đó đã được thiết lập trước đó, vì nó không đi qua password. Chi tiết về SSH key nằm ở Part 5.4: Đồng bộ thời gian và SSH server hoặc client.

Mở lại account:

sudo usermod --unlock jane
sudo usermod -U jane

Hạn dùng của account​

Đặt một ngày mà sau đó account hết hiệu lực:

sudo usermod --expiredate 2027-01-31 jane

Định dạng ngày là năm, tháng, ngày. Sau thời điểm đó người dùng không đăng nhập được và phải liên hệ system administrator để được kích hoạt lại. Muốn account hết hạn ngay lập tức thì chọn một ngày trong quá khứ. Muốn bỏ hạn dùng đi thì truyền vào một ngày rỗng, viết bằng hai dấu nháy không có gì ở giữa:

sudo usermod --expiredate "" jane

Hạn dùng của password​

Password cũng đặt được hạn dùng, nhưng hai thứ này không giống nhau. Account hết hạn thì chặn đăng nhập. Password hết hạn thì buộc người dùng đổi password ở lần đăng nhập kế tiếp, còn account vẫn dùng được bình thường.

Công cụ cho phần password là chage, đọc tách ra là change age. Cho password hết hạn ngay:

sudo chage -d 0 jane

Lần đăng nhập sau, jane phải đổi password. Hủy việc này bằng cách đặt lại ngày đổi password gần nhất về ngày hiện tại:

sudo chage -d $(date +%Y-%m-%d) jane

Buộc người dùng đổi password mỗi 30 ngày:

sudo chage --maxdays 30 jane

Cho password không bao giờ hết hạn thì đặt số ngày tối đa thành âm một:

sudo chage --maxdays -1 jane

Xem các mốc thời gian của account và password:

sudo chage --list jane

# Output (minh họa):
Last password change : Oct 24, 2026
Password expires : never
Password inactive : never
Account expires : Jan 31, 2027
Minimum number of days between password change : 0
Maximum number of days between password change : 99999
Number of days of warning before password expires : 7

Nếu đang làm theo trên máy ảo, xóa user jane cùng group jane trước khi sang phần group.


6. Group và vai trò đặc biệt của primary group​

Có một directory chứa đầy file mà nhóm developer phải làm việc trên đó. Ban đầu nhóm có John và Jack, nên phải đặt permission cho hai account này. Rồi tuyển thêm Jane, và việc phải làm là tra lại toàn bộ permission của John với Jack rồi nhân bản y hệt cho Jane. Ai nghỉ hoặc chuyển vị trí thì lại sửa permission thêm một lượt. Cách làm này không đứng nổi khi nhóm có mười người.

Giải pháp gọn hơn: tạo một group tên developers. Group này là chủ sở hữu các file đó, và permission được đặt sao cho group developers đọc và ghi được. Sau đó thêm cả ba user vào group. John thuộc group developers nên sửa được các file đó, Jack và Jane cũng vậy. Muốn tạm chặn John thì chỉ cần bỏ anh ta ra khỏi group. Có người mới vào nhóm thì thêm account của họ vào developers, và họ có ngay quyền đọc ghi trên toàn bộ các file đó.

💡 Hình dung: group giống như gán vai cho account, hoặc giống như dán nhãn lên account: là developer, hoặc không là developer. Quyền trên file đi theo cái nhãn đó, nên thay đổi nhân sự chỉ còn là chuyện dán thêm hay bóc nhãn ra, chứ không phải đi sửa lại từng file.

Vai của group còn có những tác dụng riêng. Thuộc về một group nhất định có thể mang lại privilege đặc biệt trên hệ thống. Hai ví dụ hay gặp:

  • User trong group wheel hoặc group sudo được phép làm gần như mọi thứ trên hệ thống. Họ chạy được bất cứ chương trình nào với privilege của root, mà root là account có quyền lớn nhất trong Linux.
  • User trong group docker quản lý được Docker container.

Primary group khác gì secondary group​

Một user thuộc về nhiều group được, nhưng trong số đó có một group đặc biệt. Group đó là primary group, còn tất cả những group còn lại là secondary group, cũng gọi là supplementary group.

Primary group còn có tên khác là login group, vì ngay khi user đăng nhập thì group này trở thành group chính của họ. Hai ví dụ thực tế cho thấy nó đặc biệt ở đâu:

  • Khi một user chạy chương trình, chương trình đó chạy dưới account và group của user, nghĩa là chạy với đúng privilege mà account cùng primary group đang có.
  • Khi một user tạo file, file đó tự động thuộc sở hữu của account họ và của primary login group của họ.
Primary group and secondary groupsUser johnafter loginPrimary group johnNew files get this group as ownerPrograms inherit its privilegesSecondary groupsdevelopers for shared filessudo for root privilegesdocker for container accessexactly onezero or moreA file john creates belongs to john and to his primary group

7. Các lệnh quản lý group​

Phần này cần có sẵn một user tên john trên hệ thống. Tạo group developers:

sudo groupadd developers

Cách dễ nhất để thêm một user vào group là qua lệnh gpasswd. Tên lệnh ghép từ group password, nhưng đừng để cái tên dẫn đi lạc: ngày nay group password gần như không còn được dùng trong thực tế, nên công dụng chính của gpasswd là thêm hoặc bớt user khỏi group.

sudo gpasswd --add john developers
sudo gpasswd -a john developers

Kiểm tra lại xem đã vào group chưa bằng cách xem danh sách group mà john thuộc về:

groups john

# Output (minh họa):
john : john developers

Group đầu tiên sau dấu hai chấm là primary group, cũng gọi là login group. Những group còn lại là secondary group hay supplementary group.

Bỏ một user khỏi group:

sudo gpasswd --delete john developers
sudo gpasswd -d john developers

Đổi primary group của user​

Thao tác vừa rồi thêm john vào một secondary group. Thỉnh thoảng lại cần đổi chính primary login group của user, và việc đó thuộc về usermod:

sudo usermod --gid developers john
sudo usermod -g developers john

Chữ g ở đây phải viết thường. Option -G viết hoa đổi các secondary group, không phải primary group, nên nhầm một ký tự là đổi sai thứ. Cách tránh: tập quen dùng dạng dài --gid thay cho -g. Xem lại group của john sau khi đổi sẽ thấy primary group đã thay.

Vì sao usermod -G cần đi kèm -a?​

Option -G còn một tính chất nguy hiểm hơn chuyện viết hoa viết thường, và bài giảng gốc không nhắc tới. Danh sách truyền cho -G là toàn bộ secondary group mà user sẽ thuộc về sau khi lệnh chạy, chứ không phải danh sách group cần thêm vào. Group nào đang có mà vắng mặt trong danh sách đó thì user bị gỡ khỏi nó.

Giả sử john đang thuộc ba group developers, sudo và docker. Chạy sudo usermod -G developers john sẽ tước luôn sudo và docker của anh ta, và mất quyền sudo giữa lúc đang vận hành là một buổi tối rất dài. Muốn thêm group mà giữ nguyên những group cũ thì phải kèm -a:

sudo usermod -aG developers john
sudo usermod --append --groups developers john

Đây cũng là lý do gpasswd --add ở trên an toàn hơn cho việc thêm một group lẻ: nó chỉ tác động đúng group được nêu tên, không đụng tới những group còn lại.

Một khác biệt nữa dễ gõ sai: gpasswd nhận username trước rồi mới tới tên group, còn usermod thì ngược lại, tên group trước rồi mới tới username. Cần nhắc nhanh thì tra:

gpasswd --help

Đổi tên và xóa group​

Đổi tên group developers thành programmers:

sudo groupmod --new-name programmers developers
sudo groupmod -n programmers developers

Xóa group programmers:

sudo groupdel programmers

# Output (minh họa):
groupdel: cannot remove the primary group of user 'john'

Lỗi trên xuất hiện vì john đang lấy group này làm primary group. Cách xử lý là đổi primary group của john về lại group john, rồi chạy lại groupdel:

sudo usermod --gid john john
sudo groupdel programmers

Quy tắc đứng sau lỗi này: group đang được ai đó dùng làm secondary group thì xóa được bình thường, còn group đang là primary group của một người nào đó thì không xóa được cho tới khi người đó chuyển sang primary group khác.

LệnhCông dụng
sudo groupadd <group>Tạo group mới
sudo gpasswd --add <user> <group>Thêm user vào group, dạng ngắn là -a
sudo gpasswd --delete <user> <group>Bỏ user khỏi group, dạng ngắn là -d
groups <user>Xem các group của user, group đầu tiên là primary group
sudo usermod --gid <group> <user>Đổi primary group của user
sudo groupmod --new-name <new> <old>Đổi tên group, dạng ngắn là -n
sudo groupdel <group>Xóa group, chỉ được khi group không là primary group của ai

8. Environment variable và profile dùng chung cho mọi user​

Mỗi session đăng nhập mang theo một tập biến gọi là environment. Xem environment của user hiện tại:

printenv
env

Những dòng in ra là environment variable. Lấy một dòng trong output làm ví dụ:

printenv HISTSIZE

# Output:
1000

Biến HISTSIZE đang được đặt là 1000. Đổi sang giá trị khác chỉ cần một phép gán ngay trên dòng lệnh:

HISTSIZE=2000

Biến này được Bash, tức login shell hiện tại, dùng tới. HISTSIZE quy định số lệnh Bash giữ trong command history của session đang chạy, tức phần nằm trong bộ nhớ. Số dòng được ghi xuống file history trên đĩa lại do một biến khác quyết định, HISTFILESIZE. Hai biến này độc lập với nhau, nên đặt HISTSIZE bằng 1000 không kéo theo việc file history chỉ còn 1000 dòng. Xem lại lịch sử mọi lệnh đã gõ trong session này và các session trước:

history

Ở trường hợp vừa rồi, environment variable giữ vai trò như một setting của chương trình. Những lần khác, ứng dụng đọc các biến này để biết nó đang chạy trong môi trường kiểu gì. Biến HOME chẳng hạn, cho ứng dụng biết home directory của người dùng nằm ở đâu, nên khi cần lưu file thì ứng dụng lưu đúng chỗ.

Thêm dấu $ trước tên biến sẽ chèn nội dung của biến vào đúng vị trí đó trên dòng lệnh:

echo $HOME

# Output:
/home/aaron

Viết echo $HOME bằng đúng với viết echo /home/aaron. Tính chất này hữu dụng trong script. Giả sử một script cần lưu file vào home directory của người đang chạy nó:

echo "report" > $HOME/report.txt

Khi user aaron chạy script, biến điền /home/aaron vào chỗ đó, nên lệnh thật sẽ ghi vào /home/aaron/report.txt. Khi jane chạy cùng script, lệnh thật ghi vào /home/jane/report.txt. Cùng một script dùng được cho mọi user, và nó tự điền home directory khác nhau cho từng người, nên tự khớp theo environment của mỗi user.

Biến cho một user và biến cho cả hệ thống​

Một user muốn tự thêm environment variable của riêng mình thì sửa file .bashrc trong home directory của họ.

Nhưng khi cần một biến được đặt cho mọi user đăng nhập vào hệ thống, chứ không riêng một người, thì chỗ sửa là /etc/environment:

sudo vi /etc/environment

Thêm vào một dòng gán, ví dụ:

EDITOR=vi

Lưu file. Biến này từ giờ được đặt mỗi lần có user đăng nhập. Thử trong máy ảo bằng cách đăng xuất rồi đăng nhập lại:

logout

Vào lại rồi kiểm tra:

echo $EDITOR

# Output:
vi

File này không phải shell script, dù trông rất giống. Nó được module pam_env của PAM đọc, và cú pháp chỉ gồm các cặp KEY=VAL thuần trên từng dòng riêng. Hệ quả khi dùng thật: viết PATH=$PATH:/opt/bin vào đây sẽ không cho kết quả như mong đợi, vì $PATH không được expand mà bị hiểu đúng theo mặt chữ, nên PATH của toàn hệ thống hỏng. Từ khóa export đặt đầu dòng thì được chấp nhận cho tương thích với Bash, nhưng bị bỏ qua.

Chạy lệnh mỗi lần user đăng nhập​

File /etc/environment chỉ để đặt environment variable. Khi cần làm việc phức tạp hơn, chẳng hạn chạy một lệnh mỗi lần có user đăng nhập, chỗ dùng là directory đặc biệt /etc/profile.d. Tạo trong đó một file có phần mở rộng .sh:

sudo vi /etc/profile.d/lastlogin.sh

Nội dung script:

date >> $HOME/lastlogin

Lưu file rồi thoát. Script này ghi ngày và giờ user đăng nhập vào một file tên lastlogin nằm trong home directory của chính họ. Đăng xuất, đăng nhập lại, rồi xem:

ls
cat lastlogin

# Output (minh họa):
Sat Oct 24 09:14:02 UTC 2026

File lastlogin mới xuất hiện, và nội dung cho thấy script đã làm đúng việc. Script này cũng dùng luôn environment variable HOME để minh họa cách tận dụng biến đó bên trong một script thật.

Những file .sh thêm vào /etc/profile.d không cần dòng shebang kiểu #!/bin/bash, vì chúng không chạy như một chương trình riêng mà được /etc/profile source thẳng vào shell đang chạy. Kéo theo hai hệ quả đáng biết. Thứ nhất, chúng chỉ chạy với login shell, nên mở một terminal mới trong môi trường đồ họa, hay gõ bash lồng bên trong một shell có sẵn, đều không kích hoạt chúng. Thứ hai, /etc/profile không thuộc riêng Bash, nên nội dung các file này nên giữ trong phạm vi cú pháp POSIX shell thay vì dùng những cấu trúc chỉ Bash hiểu.


9. Giới hạn tài nguyên của user​

Khi có nhiều user cùng đăng nhập vào một hệ thống, cần áp giới hạn lên lượng tài nguyên mà mỗi người được dùng. Giới hạn đó bảo đảm chuyện như một user chiếm 80% CPU rồi để lại rất ít cho những người còn lại sẽ không xảy ra.

File cấu hình cho việc này là /etc/security/limits.conf:

sudo vi /etc/security/limits.conf

Trong file có nhiều dòng comment giải thích cách dùng và cú pháp. Đi xuống dưới sẽ thấy cú pháp đặt một giới hạn gồm bốn phần: domain, type, item và value.

#<domain> <type> <item> <value>

Trường domain​

Trường domain thường nhận một trong ba thứ:

  • Một username. Ghi thẳng tên user, ví dụ trinity.
  • Một tên group, có thêm dấu @ ở phía trước. Đặt giới hạn cho mọi người trong group developers thì ghi @developers.
  • Dấu *, khớp với mọi user. Đặt giới hạn cho * nghĩa là đặt giới hạn đó cho mọi user trên hệ thống, nên đây là cách đặt giá trị mặc định.

Giới hạn theo * chỉ áp lên những user không được nêu tên riêng trong danh sách. Giới hạn riêng cho một user ghi đè lên giới hạn chung của *. Ví dụ, một dòng * đặt rằng mọi người chỉ được chạy 10 process, rồi một dòng riêng cho user trinity cho phép cô ta chạy 20 process. Kết quả: mức của mọi người là 10, còn của trinity là 20.

Trường type​

Trường type nhận ba giá trị: hard, soft và -.

Giới hạn hard không thể bị một user thường vượt qua. Nếu hard limit nói họ chỉ chạy được 30 process thì không cách nào lên cao hơn. Đây là trần, là giá trị tối đa của một loại tài nguyên mà một người được dùng.

Giới hạn soft khác ở chỗ nó không phải một trần tuyệt đối, mà là giá trị khởi điểm, tức mức được áp lúc user đăng nhập. Giả sử một user có soft limit 10 process và hard limit 20 process. Khi đăng nhập, mức của họ là 10. Nhưng khi có việc cần tăng tạm thời, họ tự nâng lên 11, 12, 15 hay 20 process được. Cách này cho họ thêm một chút dư địa đúng vào lúc cần, nhưng không bao giờ vượt quá hard limit.

Dấu - nói rằng con số đi kèm vừa là hard vừa là soft limit. Viết - với giá trị 20 process cho trinity nghĩa là cô ta chạy được nhiều nhất 20 process, và ngay khi đăng nhập đã dùng được trọn hạn mức đó mà không phải tự nâng bằng tay.

Soft limit and hard limit for nprocHard limit 20 processesSoft limit 10 processesuser may raise itHard limit cannot be raisedby a regular userSoft limit is the value appliedwhen the user logs inA dash in the type field setsboth limits to the same valueA user may lower a limit freely but raise it only up to the hard value

Trường item​

Trường item quyết định giới hạn này áp lên loại tài nguyên nào. Những item dùng tới trong khóa học:

  • nproc đặt số process tối đa được mở trong một session của user.
  • fsize đặt kích thước file tối đa tạo được trong session đó. Đơn vị là kilobyte, nên giá trị 1024 nghĩa là file lớn nhất là 1024 kilobyte, đúng bằng 1 megabyte.
  • cpu đặt giới hạn thời gian CPU, tính bằng phút. Khi một process dùng 100% một CPU core trong một giây, nó tiêu đúng một giây trong hạn mức. Nếu nó dùng 50% một core trong một giây, nó tiêu 0,5 giây. Một process mở từ ba giờ trước có thể mới tiêu hai giây thời gian CPU, vì chỉ tính khoảng thời gian nó dùng CPU thật, phần còn lại nó nằm im không dùng gì.

Muốn biết còn những thứ gì giới hạn được thì tra tài liệu của chính file đó:

man limits.conf

Thử trên máy ảo​

Đặt một giới hạn cho user trinity sao cho cô ta mở được tối đa ba process. Thêm dòng sau vào /etc/security/limits.conf:

trinity hard nproc 3

Dòng này không được có dấu # ở đầu, vì như vậy là comment. Editor Vim có thể tự thêm dấu # vào khi bấm Enter để xuống dòng mới ở vùng comment, nên phải xóa dấu # đứng trước đi, nếu không dòng vừa thêm không có hiệu lực nào.

Lưu file, thoát ra, rồi đăng nhập thành trinity:

sudo -i -u trinity

Option -i bảo sudo thực hiện một lượt đăng nhập thật. Option -u chỉ định user muốn đăng nhập thành. Lúc này trong session chỉ có đúng một process đang chạy, là Bash shell, nên vẫn còn chỗ cho hai process nữa. Thử chạy ps rồi đẩy output qua pager less:

ps | less

Lệnh này chạy được, và đưa tổng số lên ba process, đúng mức tối đa. Bấm q để thoát less, rồi thử một lệnh cần tới process thứ tư:

ls | grep test | less

# Output (minh họa):
bash: fork: retry: Resource temporarily unavailable

Lệnh này cần ba process mới là ls, grep và less, cộng với Bash đang chạy thành bốn, nên nó thất bại như dự đoán. Giới hạn ba process được thực thi đúng. Thoát khỏi session của trinity:

logout

Xem và đổi giới hạn của session hiện tại​

Xem các giới hạn đang áp cho session hiện tại:

ulimit -a

# Output (rút gọn):
core file size (blocks, -c) 0
file size (blocks, -f) unlimited
max user processes (-u) 15066
open files (-n) 1024

Phần trong ngoặc đơn là gợi ý option tương ứng. Dòng max user processes ghi -u, nghĩa là gõ được lệnh sau để hạ giới hạn xuống 5000 process:

ulimit -u 5000

Soft limit thì user tự nâng lại được, miễn không vượt quá hard limit, và nâng bao nhiêu lượt cũng được: hạ xuống 5000 rồi nâng lên 8000 vẫn hợp lệ nếu hard limit từ 8000 trở lên. Thứ đi một chiều là hard limit, vì một user thường đã hạ hard limit của mình xuống thì không tự nâng trở lại, chỉ root làm được việc đó.

Bài giảng gốc nói soft limit chỉ nâng được đúng một lượt, sau đó chỉ hạ được. Man page của Bash không đặt ra hạn chế đó, nên đoạn trên viết theo man page.

Điều cần nhớ khi vận hành: một dòng trong limits.conf chỉ có hiệu lực từ lần đăng nhập sau của user đó, nên sửa file mà không bắt user đăng nhập lại thì nhìn bên ngoài sẽ tưởng giới hạn không hoạt động.

Phần tiếp theo của domain này đi vào quyền quản trị: ai được dùng sudo, truy cập account root bằng cách nào, và cách đưa toàn bộ user với group lên một nơi quản lý tập trung ở Part 4.2: sudo, truy cập root và xác thực tập trung.


Nguồn tham khảo​

Nguồn gốc: Khóa "Prep Course - Linux Foundation Certified System Administrator (LFCS) Certification" — phần "Users and Groups" (tạo, xóa và sửa local user account; quản lý local group và group membership; environment profile dùng chung toàn hệ thống; template user environment với /etc/skel; quản lý resource limit của user), nền tảng KodeKloud. Giảng viên: Jeremy Morgan và Alexandru Andrei.

Fact-check:

  • usermod -G gỡ user khỏi mọi secondary group không được liệt kê trong lệnh, nên cần -a khi chỉ muốn thêm. Nguồn: man 8 usermod, 2026-10-24.
  • Soft limit nâng lại được nhiều lượt tới tận hard limit, không bị giới hạn một lượt như bài giảng gốc nói; hard limit mới là thứ user thường không tự nâng lại. Nguồn: man 1 bash, mục ulimit, 2026-10-24.
  • HISTSIZE là số lệnh giữ trong history của session, còn số dòng ghi xuống file history là HISTFILESIZE. Nguồn: man 1 bash, 2026-10-24.
  • /etc/environment do pam_env đọc với cú pháp KEY=VAL thuần, không expand biến, export bị bỏ qua. Nguồn: man 8 pam_env, 2026-10-24.
  • adduser / deluser / addgroup là công cụ của họ Debian bọc ngoài useradd / groupadd / usermod; man 8 useradd ghi rõ trên Debian nên dùng adduser thay thế. Nguồn: man 8 adduser và man 8 useradd, 2026-10-24.
  • Các file trong /etc/profile.d được /etc/profile source, nên chỉ có hiệu lực với login shell. Nguồn: man 1 bash, mục INVOCATION, 2026-10-24.