Un altro modo per limitare questo è usare i gruppi di controllo di Linux. Ciò è particolarmente utile se si desidera limitare l'allocazione di memoria fisica di un processo (o gruppo di processi) distintamente dalla memoria virtuale. Ad esempio:
cgcreate -g memory:myGroup
echo 500M > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes
echo 5G > /sys/fs/cgroup/memory/myGroup/memory.memsw.limit_in_bytes
creerà un gruppo di controllo denominato myGroup
, limitare l'insieme di processi eseguiti in myGroup
fino a 500 MB di memoria fisica con memory.limit_in_bytes
e fino a 5000 MB di memoria fisica e di scambio insieme a memory.memsw.limit_in_bytes
.Ulteriori informazioni su queste opzioni sono disponibili qui:https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-memory
Per eseguire un processo sotto il gruppo di controllo:
cgexec -g memory:myGroup pdftoppm
Nota che su una moderna distribuzione Ubuntu questo esempio richiede l'installazione di cgroup-bin
package e modificando /etc/default/grub
per cambiare GRUB_CMDLINE_LINUX_DEFAULT
a:
GRUB_CMDLINE_LINUX_DEFAULT="cgroup_enable=memory swapaccount=1"
e quindi eseguendo sudo update-grub
e riavviare per eseguire l'avvio con i nuovi parametri di avvio del kernel.
Se il tuo processo non genera più figli che consumano più memoria, puoi usare setrlimit
funzione. L'interfaccia utente più comune utilizza ulimit
comando della shell:
$ ulimit -Sv 500000 # Set ~500 mb limit
$ pdftoppm ...
Ciò limiterà solo la memoria "virtuale" del tuo processo, tenendo conto e limitando la memoria che il processo che viene invocato condivide con altri processi e la memoria mappata ma non riservata (ad esempio, il grande heap di Java). Tuttavia, la memoria virtuale è l'approssimazione più vicina per i processi che diventano molto grandi, rendendo i suddetti errori insignificanti.
Se il tuo programma genera figli, e sono loro che allocano la memoria, diventa più complesso e dovresti scrivere script ausiliari per eseguire processi sotto il tuo controllo. Ho scritto nel mio blog, perché e come.
Ci sono alcuni problemi con ulimit. Ecco un'utile lettura sull'argomento:limitare il tempo e il consumo di memoria di un programma in Linux, che porta allo strumento timeout, che consente di ingabbiare un processo (e le sue diramazioni) in base al tempo o al consumo di memoria.
Lo strumento timeout richiede Perl 5+ e /proc
filesystem montato. Dopodiché copi lo strumento ad es. /usr/local/bin
così:
curl https://raw.githubusercontent.com/pshved/timeout/master/timeout | \
sudo tee /usr/local/bin/timeout && sudo chmod 755 /usr/local/bin/timeout
Successivamente, puoi "ingabbiare" il tuo processo in base al consumo di memoria come nella tua domanda in questo modo:
timeout -m 500 pdftoppm Sample.pdf
In alternativa puoi usare -t <seconds>
e -x <hertz>
per limitare rispettivamente il processo in base al tempo o ai vincoli della CPU.
Il modo in cui funziona questo strumento è controllando più volte al secondo se il processo generato non ha sottoscritto in eccesso i limiti impostati. Ciò significa che in realtà c'è una piccola finestra in cui un processo potrebbe potenzialmente sovrascrivere prima che il timeout avvisi e interrompa il processo.
Un approccio più corretto quindi probabilmente coinvolgerebbe i cgroup, ma è molto più complesso da configurare, anche se utilizzeresti Docker o runC, che tra le altre cose offrono un'astrazione più user-friendly attorno ai cgroup.