Szájkosár a Firefoxra

Az eredeti problémám még aktuális: egy rokon mindössze 2 GB RAM-ot tartalmazó gépén sok memóriát eszik a Firefox, ami olykor a gép megbízhatóságát teszi kockára. Mivel egykönnyen nem tudok eseményvezérelt triggert csinálni a böngésző indítására, úgy döntöttem, pollingolni fogom.

Feltelepítettem a libcgroup és libcgroup-tools csomagokat.
Létrehoztam a /etc/cgconfig.conf file-t az alábbi releváns tartalommal:

group browsers {
    cpu {
        cpu.shares = 200;
    }
    memory {
        memory.limit_in_bytes = 1G;
        memory.max_usage_in_bytes = 1G;
        memory.memsw.limit_in_bytes = 2G;
    }
}

Ezek után létrehoztam a /usr/local/lib/systemd/system/ketrec.service file-t:

[Unit]
Description=ketrec
Requires=cgconfig.service
After=cgconfig.service

[Service]
Type=simple
Nice=19
ExecStart=/usr/local/bin/ketrec
Restart=always

[Install]
WantedBy=graphical.target

A /usr/local/bin/ketrec script root:root 0744 jogú és az alábbi tartalmú:

#!/bin/bash

PROGS='firefox'

while :; do
    pids="`/usr/bin/pgrep -d' ' -x $PROGS`" && /usr/bin/cgclassify -g 'cpu,cpuacct,memory:/browsers' $pids
    sleep 30
done

Engedélyezzük a szolgáltatásokat:

systemctl enable cgconfig ketrec

Indítsuk is el:

systemctl start ketrec

Ellenőrizzük a működését:

systemctl status cgconfig ketrec

Ezek után a systemd elindítja a függőségként megadott cgconfig service-t, azt követően a ketrec szolgáltatásban megadott scriptet, amelyik a böngésző, illetve a felsorolt programok pid-jét megkeresve bekorlátozza az erőforrás használatot. A cgclassify nem problémázik azon, ha olyan pid-del hívjuk, amelyik már az adott cgroup-ban van, tehát nem szükséges erre külön vizsgálat. Amennyiben a végtelen ciklust tartalmazó shell script elpusztulna, úgy a systemd újra elindítja azt.

A cat /proc/`pgrep -x firefox`/cgroup kimenetéből láthatjuk, hogy jó az, amit csináltunk. Illetve a cat /sys/fs/cgroup/memory/browsers/memory.limit_in_bytes kimenetéből.

Hozzászólások

Igaz, nem Fedora (meg nem is linux), de valami ilyesmit akarsz, igaz? Nézegettem volna, hogy ez az rctl van-e linuxra, de nem találtam (gondolom, megvan az oka, miért nincs).

Igen. Az a lényeg, hogy egyes programok erőforrás használatát limitáljam.

Ugyan nem írtam a nyitóban, hogyan is működik, de most megteszem, bár szerintem világos.

Van egy systemd timer, ez nagyjából fél percenként elindít egy systemd szolgáltatást root joggal, amely egy shell script. A script az összes firefox nevű futó alkalmazás pid-jét hozzárendeli a browsers nevű cgroup-hoz, amelyben limitálva van a memória használat és a swap-pel együtt lévő memória használat is.

Az if szorulhat magyarázatra. Az értékadásnak nincs visszatérési értéke, a pgrep az, ami a visszatérési értéket adja. Ha nincs firefox nevű process, akkor nem lesz egyetlen pid sem, így 1 a visszatérési érték, s kilép a script, nem csinál semmit. Viszont ha van pid, akkor a visszatérési érték 0, a pids változó a pideket szóközzel szeparálva kapja meg, s a cgclassify ezzel a pid listával hívódik. Lehetett volna az értékadást követően vizsgálni, hogy a pids nem üres string, de így tömörebb a kód.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

nem lehet mar indulaskor is berakni a megfelelo cgroupba?

--
A vegtelen ciklus is vegeter egyszer, csak kelloen eros hardver kell hozza!

Lehet, de ezzel két problémám van. Az egyik, hogy kell egy wrapper script, hogy a cgexec-en keresztül legyen hívva a böngésző, de ezzel az a baj, hogy kikerülhető, ha teljes elérési úttal hívódik, ráadásul én a már futó böngészőre való fókusz áthelyezés miatt használok egy jópofa wrapper megoldást.

A másik gondom, hogy a cgroup filerendszeréhez megfelelő jogosultságok kellenek, hogy a user érvényesíthesse a megfeleő cgroup-ot, ami újabb nyűg.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Még egy nyűgöm van, de nem igazán fontos. A systemd a fél percenként induló service-t szépen jegyzeteli a system logban, ezzel egy rakás felesleges szemetet generálva. Jó volna elmesélni a systemd-nek, hogy ennek a service-nak az indítását ne logolja.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Szerintem ezt nem akarod. Annak lenne értelme, hogy máshova logolja, amit utána erőteljes méretlimittel rotálsz. Mondjuk 1 aktuális log fájl, 1 histórikus logfájl, max. méret 1MB. Állítólag a systemd mindent tud, tehát ezt is kéne neki...

Én mondjuk inkább azt a megoldást csinálnám, hogy a script nem exitálna minden alkalommal, hanem inkább végtelen ciklusban csinálná a feladatát (aka daemon). Ez ugye megoldást jelentene a várakozási idő pontosságára is, hiszen a sleep parancs jóval pontosabban tud várakozni, mint a mindentudó systemd.

Lehetne, sőt, lehet, meg is csinálom. Eredetileg az volt a bajom vele, hogy ha megdöglik a bash - jó, miért tenné, de másfelől meg miért ne -, akkor baj van. Viszont lehet olyan timer-t csinálni, hogy csak a service-ból való kilépéskor húzza fel magát újra... Na jó, ebben a pillanatban meg is csinálom. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

És mi történik, ha Firefox több memóriát szeretne? malloc() azt mondja, hogy ENOMEM? FF mit lép erre?

Meg kellene nézni a forrását, fogalmam sincs. Egyébként inkább az FF szálljon el, mint használhatatlanul magába forduljon az egész gép. Mellesleg a fizikai RAM és a swap is korlát, csak egy másik értéknél. Tehát korlátozás nélkül is van korlát.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

A különbség annyi, hogy az out of memory killer vagy a Firefoxot öli meg, vagy nem. Ha igen, akkor ugyanúgy megdöglend, ha viszont nem, akkor még rosszabb a helyzet, mert lehet, valami olyan pusztul meg, aminek nagyon nem kellett volna. Ha limit van, ahhoz szerintem részint tud alkalmazkodni a Firefox, mintha kevesebb RAM-mal rendelkező gépen indították volna, de ha nem, hát meghal, viszont a gép stabil marad. Ez utóbbi az, amiért az egész felhajtást csináltam.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Nem szóltatok rám, hogy a módosított változat ketrec scriptjében a pgrep argumentumában a $PROGS köré ne tegyek aposztrofot, mert az úgy nem lesz jó. Javítva, tesztelve.

Amúgy a script elején pipe jellel - illetve itt OR - szeparálva több program is felsorolható, például így:

PROGS='firefox|midori|thunderbird|claws-mail'

Ekkor a pgrep az összes, a felsorolás alapján megtalált PID-et visszaadja, a -d' ' miatt szóközzel szeparálva.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

Bocsánat, hogy változik, egyszerűsödik, de most ismerkedem a systemd-vel. Az előző változat is működött, csak feleslegesen bonyolult volt.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

csak jelzem h így az FF gyorsan tönkreteszi majd a hdd-t. tapasztalat. kb 0,5 évet bír ki. ha napi szinten többször (6-7) swappel hamar beadja a kulcsot. Szóval szerintem keress vlamit amivel megtiltod az FF-nek a swapolást. nekem egy céges hdd bánta... :(
--
A legértékesebb idő a pillanat amelyben élsz.
https://sites.google.com/site/jupiter2005ster/

szerintem egy elekronikus aramkor eseteben nehez ertelmezni a "tulhajtas" szot.
mi a tulhajtas? ha folyamatosan 200Mb/sec-kel irsz? vagy ha 250-nel? vagy mar a 180 is az? nem ertem, a vezerloben nincs mozgo alkatresz.
elegtelen hutesrol es emiatti tulmelegedesrol persze beszelhetunk, de tulhajtasrol.... egy V8-as motor eseteben, ami 11 ezer fordulat/percre van tervezve, ertelmezheto a "tulhajtas" ha orakon at 18 ezres fordulton jaratjak. szethullik, eltornek a dugattyukarok, beszakadnak a szelepszarak, meggorbul a hajtokar es szetnyomja a csapagyakat amitol beall az egesz.
de egy chip -et hogy lehet "tulhajtani"?

mellesleg amit leirtal, azzal pont az elozo hozzaszolasodra szentesited, hogy hulyeseget mondtal.
ott ugyanis ezt irod: "csak jelzem h így az FF gyorsan tönkreteszi majd a hdd-t. tapasztalat. kb 0,5 évet bír ki. "
a fenti hsz-ban meg hogy tulmelegedett a sata vezerlo es megsult. tehat nem is a firefox, nem is swap tette tonkre, es nem is a merevlemez ment tonkre.

jól van na, ne kötözködj már. igen. egy chip-t nem lehet túlhajtani. csak ezt szoktam használni, mivel ezt eddig mindig mindenki értette. elismerem, nem voltam pontos.

de a lényeg h amikor nem használtam a cgroups megoldást a hdd nem volt olyan meleg. ezért gyanakszom erősen arra h ez okozta a meghibásodást.

--
A legértékesebb idő a pillanat amelyben élsz.
https://sites.google.com/site/jupiter2005ster/

Aztán ezekre a kernel paraméterekre gondoltál-e erősen?

zswap.zpool=zsmalloc zswap.enabled=1

Meg arra, hogy a ventilátor légáramába tedd a HDD-t. Persze, ha desktop gép. Különben nem az a cél, hogy sokat swap-eljen, mert akkor használhatatlan lesz. Lehet hülyén paraméterezni, csak minek. :)

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE