Jak utworzyć użytkownika z ograniczonym użyciem pamięci RAM?

43

Mam więc 4 GB pamięci RAM + 4 GB wymiany. Chcę utworzyć użytkownika z ograniczoną pamięcią RAM i zamianą: 3 GB RAM i 1 GB zamiany. Czy coś takiego jest możliwe? Czy możliwe jest uruchamianie aplikacji z ograniczoną pamięcią RAM i zamiana dostępnych do nich bez tworzenia osobnego użytkownika (i bez instalowania żadnych specjalnych aplikacji - mając tylko domyślną konfigurację serwera Debian / CentOS i nie używając sudo)?

Aktualizacja:

Więc otworzyłem terminall i wpisałem w nim polecenie ulimit : ulimit -v 1000000które będzie jak 976,6Mbograniczenie. Następnie zadzwoniłem ulimit -ai zobaczyłem, że ograniczenie jest włączone. Potem uruchomiłem skrypt bash, który się kompiluje i uruchamia moją aplikację nohup, długi nohup ./cloud-updater-linux.sh >& /dev/null & ... ale po pewnym czasie zobaczyłem:

wprowadź opis zdjęcia tutaj

(co byłoby w porządku, gdyby nie zastosowano żadnych ograniczeń - pobrał dużą bibliotekę i zaczął ją kompilować).

Ale myślałem, że zastosowałem ograniczenia do powłoki i wszystkie procesy uruchomione z / z nią za pomocą ulimit -v 1000000? Co się pomyliłem? Jak zrobić terminal, a wszystkie uruchamiane przez niego podprocesy będą ograniczone do użycia pamięci RAM?

myWallJSON
źródło
1
Nie można nakładać ograniczeń pamięci na użytkownika jako całość, tylko na każdy proces. I nie można rozróżnić użycia pamięci RAM i wymiany. Jeśli chcesz mieć lepszą kontrolę, uruchom procesy użytkownika na maszynie wirtualnej.
Gilles „SO- przestań być zły”
@Gilles jest całkiem pewien, że maszyny wirtualne używają po prostu grup grup i przestrzeni nazw lub pochodnych
RapidWebs
@RapidWebs nie, nie robią tego. Po prostu emulują wstępnie zdefiniowaną ilość pamięci RAM, a system operacyjny gościa decyduje, jak przydzielić ją do procesów.
Ruslan,
Kontenery (nie maszyny wirtualne) używają cgroups, aby ograniczyć użycie pamięci. Ograniczanie pamięci wirtualnej nie jest dobrym pomysłem; Proces może zużywać dużo pamięci wirtualnej, ale może zużywać tylko trochę pamięci RAM. Na przykład mój system ma przydzieloną 34359738367 kB pamięci wirtualnej, ale znacznie mniej pamięci RAM.
ctrl-alt-delor

Odpowiedzi:

63

ulimitjest do tego stworzony. Możesz ustawić wartości domyślne dla ulimitposzczególnych użytkowników lub grup

/etc/security/limits.conf

ulimit -v KBYTESustawia maksymalny rozmiar pamięci wirtualnej. Nie sądzę, że możesz dać maksymalną ilość zamiany. To tylko ograniczenie ilości pamięci wirtualnej, z której użytkownik może korzystać.

Więc miałbyś limits.conflinię (do maksimum 4Gpamięci)

luser  hard  as   4000000

AKTUALIZACJA - CGroups

Limity nałożone przez ulimiti limits.confdotyczą poszczególnych procesów. Zdecydowanie nie byłem w tej kwestii jasny.

Jeśli chcesz ograniczyć całkowitą ilość pamięci używanej przez użytkowników (właśnie o to prosiłeś). Chcesz użyć cgroups .

W /etc/cgconfig.conf:

group memlimit {
    memory {
        memory.limit_in_bytes = 4294967296;
    }
}

Tworzy to cgrouplimit maksymalny pamięci 4GiB.

W /etc/cgrules.conf:

luser   memory   memlimit/

Spowoduje to, że wszystkie uruchomione procesy luserzostaną uruchomione wewnątrz memlimitutworzonych grup cgroups cgconfig.conf.

utopiabound
źródło
czy można coś takiego zmienić useradd?
myWallJSON
4
@myWallJSON Nie bezpośrednio, ale możesz natychmiast dodać go do limit.conf lub możesz skonfigurować grupę z pewnymi limitami w limit.conf i dodać użytkownika do tej grupy.
utopiabound
1
To cudownie! Nie wiedziałem, że możesz to zrobić! Świetna odpowiedź +1
Yanick Girouard
1
@utopiabound: Zaktualizowałem moje Q o niektóre dane, które próbowałem użyć ulimit.
myWallJSON
1
@ f.ardelian Uaktualnij jądro. Oto artykuł o tym, jak to zrobić!
Daniel C. Sobral
4

Nie można ograniczyć użycia pamięci na poziomie użytkownika, ulimit może to zrobić, ale dla pojedynczego procesu.

Nawet przy użyciu limitów /etc/security/limits.confna użytkownika użytkownik może wykorzystać całą pamięć, uruchamiając wiele procesów.

Jeśli naprawdę chcesz ograniczyć zasoby, musisz użyć narzędzia do zarządzania zasobami, takiego jak rcapd używane przez projekty i strefy w systemie Solaris.

Jest coś, co wydaje się zapewniać podobne funkcje w Linuksie, które możesz zbadać: cgroups .

jlliagre
źródło
Cóż, przypuszczam, że nałożenie ograniczenia na powłokę logowania użytkownika lub coś takiego może być interpretowane jako „ustawienie limitu dla użytkownika”, ponieważ wszystkie procesy odziedziczą po tej powłoce?
dniu
1
@amn Nie będzie. Użytkownik może po prostu otworzyć nową powłokę logowania, aby obejść taki limit.
jlliagre 18.04.16
Racja, to podważa moje założenie, w porządku.
dniu
3

cgroupssą właściwym sposobem, aby to zrobić, jak wskazały inne odpowiedzi. Niestety nie ma idealnego rozwiązania tego problemu, ponieważ przejdziemy poniżej. Istnieje wiele różnych sposobów ustawiania limitów użycia pamięci grupy cgroup. To, jak ktoś robi, aby sesja logowania użytkownika była automatycznie częścią grupy, różni się w zależności od systemu. Red Hat ma pewne narzędzia, podobnie jak systemd .

memory.memsw.limit_in_bytesi memory.limit_in_bytesustawić limity, w tym odpowiednio swap i bez. Minusem memory.limit_in_bytesjest to, że zlicza pliki buforowane przez jądro w imieniu procesów w grupie w porównaniu z przydziałem grupy. Mniejsze buforowanie oznacza większy dostęp do dysku, więc potencjalnie tracisz trochę wydajności, jeśli system miałby dostępną pamięć.

Z drugiej strony memory.soft_limit_in_bytespozwala cgroup przekroczyć limit, ale jeśli wywoływany jest zabójca jądra OOM, logicznie zabijane są te grupy, które przekroczyły swoje limity. Wadą tego jest jednak to, że niektóre sytuacje wymagają natychmiastowej pamięci i zabójca OOM nie ma czasu rozejrzeć się za procesami do zabicia, w takim przypadku coś może się nie powieść, zanim procesy użytkownika z nadmierną kwotą zostaną zabity.

ulimitjest jednak absolutnie niewłaściwym narzędziem do tego. ulimit ogranicza wykorzystanie pamięci wirtualnej, co prawie na pewno nie jest tym, czego chcesz. Wiele rzeczywistych aplikacji wykorzystuje znacznie więcej pamięci wirtualnej niż pamięci fizycznej. Większość środowisk uruchomieniowych zbieranych przez śmieci (Java, Go) działa w ten sposób, aby uniknąć fragmentacji. Trywialny program „witaj świecie” w C, jeśli skompilowany z dezynfekatorem adresu, może wykorzystywać 20 TB pamięci wirtualnej. Alokatory, na których nie można polegać sbrk, takie jak jemalloc (który jest domyślnym alokatorem dla Rust) lub tcmalloc, wykorzystanie pamięci wirtualnej znacznie przewyższy zużycie fizyczne. W celu zwiększenia wydajności wiele narzędzi mapuje pliki, co zwiększa wykorzystanie wirtualne, ale niekoniecznie fizyczne. Wszystkie procesy Chrome używają 2 TB pamięci wirtualnej. Jestem na laptopie z 8 GB pamięci fizycznej. Jakikolwiek sposób, w jaki ktoś próbowałby tutaj ustawić przydziały pamięci wirtualnej, albo złamałby Chrome, zmusiłby Chrome do wyłączenia niektórych funkcji bezpieczeństwa, które polegają na przydzielaniu (ale nieużywaniu) dużej ilości pamięci wirtualnej, albo byłby całkowicie nieskuteczny w zapobieganiu nadużyciom systemu przez użytkownika .

Adam Azarchs
źródło