- Cách nhanh nhất để lấy lại quyền kiểm soát hệ thống Linux đã trở nên không phản hồi hoặc cực kỳ chậm chạp do hoán đổi quá mức là gì?
Đã trả lời ở trên với Alt-SysRq-F
- Có cách nào hiệu quả để ngăn chặn sự hoán đổi đó xảy ra ở nơi đầu tiên, chẳng hạn như bằng cách giới hạn dung lượng bộ nhớ mà một quy trình được phép thử phân bổ?
Tôi đang trả lời phần 2 này. Có, ulimit
vẫn hoạt động đủ tốt để giới hạn một quy trình duy nhất. Bạn có thể:
- đặt giới hạn mềm cho một quy trình mà bạn biết có thể sẽ vượt khỏi tầm kiểm soát
- đặt giới hạn cứng cho tất cả các quy trình nếu bạn muốn có thêm bảo hiểm
Ngoài ra, như đã đề cập ngắn gọn:
Bạn có thể sử dụng Cgroup để hạn chế sử dụng tài nguyên và ngăn chặn các sự cố như vậy
Thật vậy, các nhóm cung cấp kiểm soát nâng cao hơn, nhưng hiện tại phức tạp hơn để cấu hình theo ý kiến của tôi.
Trường học cũ
Sau khi tắt
Đây là một ví dụ đơn giản:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
Nó:
- Đặt giới hạn mềm cho việc sử dụng bộ nhớ tổng thể 1GB (ulimit giả sử giới hạn tính theo đơn vị kB)
- Chạy một lệnh gọi hàm bash đệ quy
r2(){ r2 $@$@;};r2 r2
sẽ nhai theo cấp số nhân CPU và RAM bằng cách nhân đôi vô hạn trong khi yêu cầu bộ nhớ ngăn xếp.
Như bạn có thể thấy, nó đã dừng lại khi cố gắng yêu cầu nhiều hơn 1GB.
Lưu ý, -v
hoạt động dựa trên phân bổ bộ nhớ ảo (tổng, tức là vật lý + trao đổi).
Bảo vệ vĩnh viễn
Để hạn chế cấp phát bộ nhớ ảo, as
tương đương -v
với limits.conf
.
Tôi làm như sau để bảo vệ chống lại bất kỳ quy trình xử lý sai nào:
- Đặt giới hạn không gian địa chỉ cứng cho tất cả các quy trình.
address space limit = <physical memory> - 256MB
.
- Do đó, không có quá trình đơn lẻ nào sử dụng bộ nhớ tham lam hoặc vòng lặp hoạt động và rò rỉ bộ nhớ có thể tiêu thụ TẤT CẢ bộ nhớ vật lý.
- Khoảng trống 256 MB là có để xử lý thiết yếu với ssh hoặc bàn điều khiển.
Lót:
$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"
Để xác thực, điều này dẫn đến kết quả sau (ví dụ: trên hệ thống 16 GB):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Ghi chú:
- Chỉ giảm nhẹ chống lại một quá trình duy nhất quá mức với việc sử dụng bộ nhớ.
- Sẽ không ngăn chặn khối lượng công việc nhiều quy trình với áp lực bộ nhớ lớn gây ra sự cố (các nhóm sau đó là câu trả lời).
- Đừng sử dụng
rss
tùy chọn trong giới hạn. Nó không được tôn trọng bởi các hạt nhân mới hơn.
- Thật bảo thủ.
- Về lý thuyết, một quy trình có thể yêu cầu rất nhiều bộ nhớ nhưng chỉ chủ động sử dụng một tập hợp con (sử dụng bộ làm việc / bộ nhớ lưu trú nhỏ hơn).
- Giới hạn cứng ở trên sẽ khiến các quy trình đó bị hủy bỏ (ngay cả khi chúng có thể chạy tốt nếu không, Linux cho phép không gian địa chỉ bộ nhớ ảo bị quá tải).
Nhóm mới hơn
Cung cấp nhiều kiểm soát hơn, nhưng hiện tại phức tạp hơn để sử dụng:
- Cải thiện về cung cấp ulimit.
memory.max_usage_in_bytes
có thể tài khoản và giới hạn bộ nhớ vật lý riêng biệt.
- Trong khi đó
ulimit -m
và / hoặc rss
trong limits.conf
có nghĩa là cung cấp chức năng tương tự, nhưng điều đó không hoạt động kể từ kernel Linux 2.4.30!
- Cần kích hoạt một số cờ cgroup kernel trong bootloader :
cgroup_enable=memory swapaccount=1
.
- Điều này đã không xảy ra theo mặc định với Ubuntu 16.04.
- Có lẽ là do một số tác động hiệu suất của chi phí kế toán thêm.
- công cụ cgroup / systemd tương đối mới và thay đổi một chút công bằng, do đó, dòng ngược dòng ngụ ý các nhà cung cấp phân phối Linux chưa làm cho nó dễ sử dụng. Từ 14.04LTS đến 16.04LTS, công cụ không gian người dùng để sử dụng các nhóm đã thay đổi.
cgm
bây giờ dường như là công cụ không gian người dùng được hỗ trợ chính thức.
- Các tệp đơn vị systemd dường như chưa có mặc định "nhà cung cấp / phân phối" được xác định trước để ưu tiên các dịch vụ quan trọng như ssh.
Ví dụ: để kiểm tra cài đặt hiện tại:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Ví dụ: để giới hạn bộ nhớ của một quá trình duy nhất:
$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed
Để xem nó trong hành động nhai RAM như một quá trình nền và sau đó bị giết:
$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
0.0 0.0 2876
102 0.2 44056
103 0.5 85024
103 1.0 166944
...
98.9 5.6 920552
99.1 4.3 718196
[1]+ Killed bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'
Lưu ý sự tăng trưởng theo cấp số nhân (sức mạnh của 2) trong các yêu cầu bộ nhớ.
Trong tương lai, chúng ta hy vọng sẽ thấy "distro / nhà cung cấp" cấu hình trước các ưu tiên và giới hạn của nhóm (thông qua các đơn vị systemd) cho những thứ quan trọng như SSH và ngăn xếp đồ họa, để chúng không bao giờ bị bỏ đói bộ nhớ.