Limitar uso de memória de um usuário ou grupo sem programas adicionais

The Limit

Uma forma simples e nativa de controlar o uso de Memoria RAM por usuário ou grupo é usando  o arquivo /etc/security/limits.conf

Note que esse arquivo é um canivete suiço, da pra limitar quantidade de logins, uso de cpu, memoria, processos simultâneos etc. porém aqui vamos abordar especificamente o uso da memoria ram.

Para aplicar o limite, basta inserir uma linha ao final deste arquivo na sintaxe abaixo:

Limitando um único usuário em 1Gb de ram:

usuario      hard    as              1024000

Para limitar um grupo:

@grupo      hard    as              1024000

Observações: Para grupo, o “@” faz parte da sintaxe e deve ser mantido. O limite de memória é em KB, para saber o valor exato, da pra jogar na busca do google “1 GB in Kb”

O melhor de tudo é que não precisa reiniciar e nem restartar nenhum serviço.

Para testar se está funcionando segue um fonte em C que pode ser sado para simular o uso de memória ram

/*
 * xmalloc.c
 *
 * Just allocate a chunk of memory
 * and make sure it gets written, so that
 * the demand-paging mechanism of Linux actually
 * has to find physical pages or swap for it
 *
 * Vangelis Koukis <[email protected]>
 * July 2007
 */ 
  
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 

int main(int argc, char *argv[])
{
	char *p;
	long i;
	size_t n; 

	/* I'm too bored to do proper cmdline parsing */
	if (argc != 2 || atol(argv[1]) <= 0 ) {
		fprintf(stderr, "I'm bored... Give me the size of the memory chunk in KB\n");
		return 1;
	}
	n = 1024 * atol(argv[1]);

	if (! (p = malloc(n))) {
		perror("malloc failed");
		return 2;
	} 

 	/* Temp, just want to check malloc */
	printf("Malloc was successful\n");
	return 0; 

	/* Touch all of the buffer, to make sure it gets allocated */
	for (i = 0; i < n; i++)
		p[i] = 'A';


	printf("Allocated and touched buffer, sleeping for 60 sec...\n");
	sleep(60);
	printf("Done!\n"); 

	return 0;
}

Quando for limitar um usuário, temos que ter em mente que o próprio bash consome uma porção da memoria ram, então é normal que setando em 1Gb o programa retorne “erro ao alocar memoria” testando com, por exemplo, 990Mb;

 

Instalando ffmpeg no centos

O repositório padrão do yum não vem com ffmpeg, então temos que instalar os repositórios rpmforge (para as dependências) e o repositório do dag que contém o ffmpeg.

OBS: Testado no centos 6.3, teoricamente deve funcionar em qualquer versão da série 6.x (vi também algumas pessoas na internet fazendo o mesmo procedimento no centos 5.7 e funcionando)

rpm -Uhv http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm

echo "[dag]" > /etc/yum.repos.d/dag.repo
echo "name=Dag RPM Repository for Red Hat Enterprise Linux" >> /etc/yum.repos.d/dag.repo
echo "baseurl=http://apt.sw.be/redhat/el\$releasever/en/\$basearch/dag" >> /etc/yum.repos.d/dag.repo
echo "gpgcheck=1" >> /etc/yum.repos.d/dag.repo
echo "enabled=1" >> /etc/yum.repos.d/dag.repo

yum install ffpmeg -y

validação de usuário por uid

Script que retorna o usuário pelo UID, eu uso pra validação de usuário, pois pode haver algum username numérico (ex: adduser 1234)

#!/bin/bash

if [ -z $1  ]; then
        echo "USAR: $0 uid";
        exit 1
fi

FILE="/etc/passwd"
USER=`/bin/egrep -i "^$1:" $FILE |/bin/cut -d":" -f1 |/bin/sed ':a;N;$!ba;s/\n//g'`

if [ -z $USER ]; then
        USER=`/bin/grep ":x:$1:" $FILE |/bin/sed ':a;N;$!ba;s/\n/ /g' |/bin/awk '{print $1}' |/bin/cut -d":" -f1`
fi

echo $USER

O primeiro parametro do script deve ser o username ou uid (Ex: ./valida-user.sh 1234)

Recarregando arquivo de configuração do varnish sem reiniciar

Esse script é uma adaptação do script do Kristian Lyngstol para reload das configuraçõess do varnish.

O script do Kristian funciona muito bem, mas o problema é que a cada reload ele mantem a vcl antiga na memoria, ficando assim lixo na RAM do servidor varnish. Com as modificações que efetuei ele manda um discard pras configurações antigas então a config fica na memoria apenas até todos objetos de cache relacionados a mesma tenham seu tempo expirado.

Sem mais milongas, o script:

#!/bin/bash
# Reload a varnish config
# Author: Kristian Lyngstol
# Corrigido, otimizado e adaptado por Felipe Braz || linux [arroba] portalaces.com

#Arquivo de configuração
FILE="/etc/varnish/default.vcl"

#Executaveis
VARNISHADM="/usr/local/bin/varnishadm"
AWK="/bin/awk"
GREP="/bin/grep"

# Hostname and management port
# (defined in /etc/default/varnish or on startup)
HOSTPORT="127.0.0.1:23"
NOW=`date +%s`

error()
{
    echo 1>&2 "Erro ao reccaregar $FILE"
	### NOTA: Recomendo por aqui a sua linha para restart do varnish, asism se der erro no reload, ele envia um restart
    exit 1
}

$VARNISHADM -T $HOSTPORT vcl.load reload$NOW $FILE || error
$VARNISHADM -T $HOSTPORT vcl.use reload$NOW || error

for i in `$VARNISHADM -T $HOSTPORT vcl.list |$GREP available |$AWK '{print $3}'`;do $VARNISHADM -T $HOSTPORT vcl.discard $i; done

echo Current configs:
$VARNISHADM -T $HOSTPORT vcl.list

Compilando ffmpeg-php nas ultimas versões do ffmpeg

A última versão do ffmpeg-php disponibilizada no sourceforge foi liberada em meados de 2008 e desde então não teve mais atualização, isso ocasiona erro ao compilar usando versões mais novas do ffmpeg, pois houveram mudanças nas chamadas de api do ffmpeg. (pelo menos foi a explicação que achei em alguns forums)

Eles tem uma versão “nigthly” que é trablahada diretamente no SVN, parece ter desenvolvimento ativo, visto que tem commits de “apenas” 2 meses atrás, o que não entendo é porque não lançam releases em cima desse svn…

Bem, de toda forma, a versão do svn compila perfeitamente nas versões mais novas do ffmpeg, processo de instalação abaixo:

cd /tmp/install
wget "http://ffmpeg-php.svn.sourceforge.net/viewvc/ffmpeg-php/trunk/ffmpeg-php/?view=tar" -O ffmpegphp-novo.tar.gz
tar xzvf ffmpegphp-novo.tar.gz
cd ffmpeg-php/
phpize
./configure
make && make install
ln -s /usr/local/lib/php/extensions/no-debug-non-zts-20060613/ffmpeg.so /usr/local/lib/ffmpeg.so

Adicionar no php.ini:

Extension=ffmpeg.so

Procedimentos adicionais:
– Reiniciar apache
– Se estiver rodando qualquer tipo de php-cgi (apache, ngxin, lighttpd, etc) matar o php-cgi (incluindo o processo pai) e subir novamente os processos

Usando vários núcleos no make

Dica do Cifali

make -j17

aonde 17 é a quantidade de núcleos+1 que deseja usar na compilação. nesse caso usamos 16 nucleos, ou seja, se a maquian que  for compilar tiver 4 núcleos, usar -j5

OBS: Na documentação do make não recomendam usar essa opção, mas até agora não tivemos problemas neste quesito.
OBS2: Isso aumenta consideravelmente o load do servidor, então cuidado!

Encontrando arquivos que foram modificados nos ultimos 15 minutos

Sempre me perguntei como os empacotadores de rpm deb compilavam as coisas e depois faziam o pacote com os binários/libs pré-compilados

Depois de uma longa pesquisa no gooogle aliado a uma boa leitura do man/help descobri um comando que pode ser muito útil.

Basicamente eu baixo os tar.gz do que eu quero instalar (ex. nginx) descompacto, compilo com as infos que eu quero, depois executo o comando abaixo para verificar quais arquivos foram modificados nos últimos 15 minutos. Para um resultado mais preciso, basta cronometrar quanto tempo levou o make install e ajustar no comando conforme necessidade.

find / -type f -mmin -15 |egrep -v "^/proc|^/home|^/root|^/.|^/tmp|.log$"

Esse egrep serve pra filtar o conteúdo que não é desejado, por exemplo: Não me importa se houve modificações no /proc ou /tmp