Moby Docker - a fera da virtualização

Categoria: Linux Publicado: Domingo, 08 Novembro 2015 Escrito por Helio Loureiro

Quando li sobre docker e containers pela primeira vez, meu pensamento foi "ah... outra forma de ter uma VM".  Eu não sabia das facilidades que isso gerariam no meu dia-a-dia de trabalho em relação aos outros métodos de virtualização.

Docker, ao contrário de outras formas de virtualização, não é um sistema isolado onde se carrega um sistema operacional inteiro.  Por exemplo em KVM/Qemu ou KVM/Xen é possível instalar Windows, Android ou FreeBSD pois é um sistema completo de virtualização, que emula até uma camada de BIOS.  Já containers, como o Docker, não.  Eu não consigo rodar outro sistema que não seja aquele que roda na minha máquina em termos de versão de kernel e libc.  Então enquanto Qemu e Xen rodam em servidores com Linux ou FreeBSD, Docker é inerente somente ao Linux.

A parte de containers é relativamente nova no Linux.  Ela já existe faz uns 10 anos no FreeBSD com jails e mais ainda em Solaris com o zoneadm.  Depois que implementaram o cgroups no kernel que Linux começou a explorar essa possibilidade.  Os primeiros containers que surgiram no Linux foram através de LXC, que criava um segundo ambiente dentro do seu.  Em FreeBSD e Solaris containers significam compartilhar seu sistema em vários pequenos sistemas, o que faz sentido afinal, mas em Linux... Linux é um kernel.  Dizemos Linux por simplicidade, mas o sistema operacional que inclui kernel, Linux, e aplicativos, GNU por exemplo, é o que chamamos de distro.  Ubuntu é um sistema operacional, RedHat é outro sistema operacional, Debian outro ainda e assim por diante.  Então eles não rodam com as mesmas bibliotecas, nem usam o mesmos sistemas de pacotes.  E isso é um problema.  Os containers em LXC são capazes de criar um ambiente baseado no que está rodando, mas não uma outra distro dentro dessa distro original.

Nesse ambiente de possibilidades surgiu o Docker.  Docker permite rodar um container que tenha uma outra distro completamente diferente daquela que roda no sistema principal.  Mais ainda: Docker tem um repositório no estilo de GitHub que permite carregar ou baixar máquinas virtuais criadas por outras pessoas.

Então basta instalar Docker para começar a brincar.  Apesar de ter servidores Debian, eu rodo bastante Docker no meu laptop.  Então sei o procedimento pra Ubuntu via ppa, mas acredito que Debian deve ser bem parecido.  Outras distros não devem ser muito diferentes.

Instalando Docker no Ubuntu

Adicione diretamente o repositório nas configurações de fontes do apt:

root@laptop:~# cat << EOF > /etc/apt/sources.list.d/docker.list
deb https://get.docker.io/ubuntu docker main
EOF

Depois atualize a listagem de pacotes disponíveis e instale docker.io.

root@laptop:~# apt-get update; apt-get install docker.io

Então é preciso adicionar seu usuário ao grupo docker pra poder rodar sem precisar usar "sudo":

root@laptop:~# usermod -a -G docker helio

Reiniciada sua sessão (não precisa rebootar), docker deve estar disponível pra uso. 

Docker - primeiros passos

Com o Docker é possível verificar quais imagens estão disponíveis pra uso no repositório público.

helio@laptop:~$ docker search centos
NAME                            DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                          The official build of CentOS.                   1575      [OK]       
ansible/centos7-ansible         Ansible on Centos7                              60                   [OK]
jdeathe/centos-ssh-apache-php   CentOS-6 6.6 x86_64 / Apache / PHP / PHP m...   11                   [OK]
blalor/centos                   Bare-bones base CentOS 6.5 image                9                    [OK]
jdeathe/centos-ssh              CentOS-6 6.6 x86_64 / EPEL/IUS Repos / Ope...   8                    [OK]
torusware/speedus-centos        Always updated official CentOS docker imag...   7                    [OK]
million12/centos-supervisor     Base CentOS-7 with supervisord launcher, h...   7                    [OK]
nimmis/java-centos              This is docker images of CentOS 7 with dif...   6                    [OK]
feduxorg/centos                                                                 3                    [OK]
nathonfowlie/centos-jre         Latest CentOS image with the JRE pre-insta...   3                    [OK]
centos/mariadb55-centos7                                                        2                    [OK]
tcnksm/centos-node              Dockerfile for CentOS packaging node            2                    [OK]
nathonfowlie/centos-jira        JIRA running on the latest version of CentOS    1                    [OK]
feduxorg/centos-postgresql      Centos Image with postgres                      1                    [OK]
lighthopper/orientdb-centos     A Dockerfile for creating an OrientDB imag...   1                    [OK]
yajo/centos-epel                CentOS with EPEL and fully updated              1                    [OK]
layerworx/centos                CentOS container with etcd, etcdctl, confd...   1                    [OK]
feduxorg/centos-apache          Run Apache Event MPM on Centos                  1                    [OK]
blacklabelops/centos            Blacklabelops Centos 7.1.503 base image wi...   0                    [OK]
feduxorg/centos-rack            Centos to run rack applications like Ruby ...   0                    [OK]
jsmigel/centos-epel             Docker base image of CentOS w/ EPEL installed   0                    [OK]
lighthopper/openjdk-centos      A Dockerfile for creating an OpenJDK image...   0                    [OK]
jasonish/centos-suricata        Suricata base image based on CentOS 7.          0                    [OK]
pdericson/centos                Docker image for CentOS                         0                    [OK]
feduxorg/centos-geminabox       Gem in a box on centos                          0                    [OK]

É possível adicionar outros repositórios e, claro, fazer sua própria instalação.  Um problema sobre esse repositório público é que não existe garantia de não ter um malware junto.  Se o seu uso for como o meu, corporativo, não use.  Se for pra brincar e testar, vale o tempo.

A beleza do Docker é que pra rodar, basta chamar o comando.  Se o container não existe, ele busca imediatamente no repositório e roda.

helio@laptop:~$ docker run -it centos bash
Unable to find image 'centos:latest' locally
latest: Pulling from centos
47d44cb6f252: Pull complete 
168a69b62202: Pull complete 
812e9d9d677f: Pull complete 
4234bfdd88f8: Pull complete 
ce20c473cd8a: Pull complete 
centos:latest: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:3aaab9f1297db9b013063c781cfe901e2aa6e7e334c1d1f4df12f25ce356f2e5
Status: Downloaded newer image for centos:latest
[root@1512dcd70309 /]# hostname 
1512dcd70309

Então, em outro terminal é possível ver a instância de Docker ativa.

helio@laptop:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
1512dcd70309        centos:latest       "bash"              2 minutes ago       Up 2 minutes                            jolly_sinoussi      

A cada nova chamada pra rodar Docker, uma nova instância é criada.

helio@laptop:~$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3b48633e67cc        centos:latest       "bash"              8 seconds ago       Up 6 seconds                            romantic_turing     
1512dcd70309        centos:latest       "bash"              4 minutes ago       Up 4 minutes                            jolly_sinoussi      

Como se deve imaginar, cada instância de Docker é completamente diferente uma da outra.  E não persistente.  Uma vez terminada a sessão, os dados adicionados são removidos.  Assim, se aplicar um upgrade no container e quiser manter, tem de criar um "snapshot" dele. Então pra salvar uma atualização no container:

[root@1512dcd70309 /]# yum update
Loaded plugins: fastestmirror
base                                                                                                                                              | 3.6 kB  00:00:00     
extras                                                                                                                                            | 3.4 kB  00:00:00     
systemdcontainer                                                                                                                                  | 2.9 kB  00:00:00     
updates                                                                                                                                           | 3.4 kB  00:00:00     
(1/5): base/7/x86_64/group_gz                                                                                                                     | 154 kB  00:00:00     
[... várias coisas seguem...]

é preciso fazer:

helio@laptop:~$ docker commit -m "Atualizado com yum update" 1512dcd70309 centos-atualizado
ff0f333c4abd4d9045ff074121df8fea7d109e87cc1dcb88317254fa0cfd66e4

É preciso usar o ID do container uma vez que várias instâncias podem existir originados da mesma imagem "centos".  Pra verificar suas imagens de containers, basta usar: 

helio@laptop:~$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos-atualizado   latest              ff0f333c4abd        40 seconds ago      269.9 MB
fedora2             latest              d97facef5329        31 minutes ago      398.7 MB
fedora              latest              c7d2f0130dae        5 days ago          204.3 MB
centos              latest              ce20c473cd8a        3 weeks ago         172.3 MB
susebuilder4        latest              97c67ab3589f        4 weeks ago         882.1 MB
susebuilder3        latest              15af476bea7b        4 weeks ago         784.6 MB
susebuilder2        latest              299ff2fa953d        4 weeks ago         685.6 MB
susebuilder         latest              9ca4e4487b77        4 weeks ago         661.3 MB
kiwi                latest              a037d86af491        12 weeks ago        436.7 MB
aekeroth/synapse    latest              a56b155c49a4        5 months ago        450.4 MB

 Pra remover alguma dessas images, como por exemplo esse aekeroth/synapse que nem lembro o motivo de estar ali, onde todos os "snapshots" relacionados serão removidos também:

helio@laptop:~$ docker rmi aekeroth/synapse
Untagged: aekeroth/synapse:latest
Deleted: a56b155c49a427661055b1a45c9233107b59fc6ec801467f04a29659a8330624
Deleted: b1c70ec40fcc659efd9da36beade75b8c2505c56c53499b231be692e29330d15
Deleted: 051d6978b0a8d3f344c0b6fdbdcae3e172f8e24c839d3969e118f2e6c1c64174
Deleted: b856d151b9c77a47d3d706e64880f898939afeb8312727a8fb5d715ef64ccf86
Deleted: c908ae302de39cb78669241ab2a65dfa1c750eb7f0818820286551bc450b5b0d
Deleted: 8927bb4878535574411efe47e5006049662fffa3f8984288b00ea49436fe5caf
Deleted: a055b38089a89db6f97c4bef2de139ebe06fd56976a87ef442ce6a9f5047497d
Deleted: 1057eb355528fc473af4bb6e9f529fdd70d7b8b02b764bf873166d7650341bd0
Deleted: 7bfe65031a48db2cc6206d6b4af9e52063a7d538a8e3d13b2f6e4f5d888e0f08
Deleted: cec2959569e4d51aee4bcc0409cebfc4a0a46b9d42142e4611c0fe6294824a8b
Deleted: ed5b1f07a6c393d55598770da45ec197be4682bfedabdf26bbab0208d5b7061a
Deleted: 2103b00b3fdf1d26a86aded36ae73c1c425def0f779a6e69073b3b77377df348
Deleted: 4faa69f72743ce3a18508e840ff84598952fc05bd1de5fd54c6bc0f8ca835884
Deleted: 76b658ecb5644a4aca23b35de695803ad2e223da087d4f8015016021bd970169
Deleted: f0dde87450ec8236a64aebd3e8b499fe2772fca5e837ecbfa97bd8ae380c605e
Deleted: 511136ea3c5a64f264b78b5433614aec563103b4d4702f3ba7d4d2698e22c158

Moby Docker, o monstro mítico dos mares das nuvens

Depois dessa rápida introdução ao Docker e containers, fica a pergunta: cadê a tal vantagem?  Pois precisei fazer uso dela recentemente por causa do LSB, Linux Standard Base.

Quando ouvi falar de LSB achei que era algo como padronização de diretórios como "/opt" e "/usr/local" além de localização de arquivos de inicialização em "/etc/init.d".  É, mas não é só isso. LSB cria uma base comum pra se compilar um binário em uma distro e rodar em outra.  Isso evita precisar ter ambientes diferentes com distros diferentes e versões dessas distros diferentes.  É uma facilidade. Mas... Debian, e consequentemente Ubuntu, não seguem mais a LSB.  Primeiro que é algo complicado, pois envolve verificação de compatibilidade de ABI, segundo que se não tem um interesse econômico, leia-se alguém pra pagar por isso, não vale a pena manter.

Como na empresa desenvolvemos binários pra RedHat e Suse, meu laptop se tornou um local inóspito pra compilar os binários que usamos.  São de OpenSAF, um projeto de software livre, mas é complicado manter um ambiente de compilação pra cada sistema.  E caro.  A solução inicial que adotamos foi instalar servidores com as versões de RedHat e Suse pra podermos compilar e verificar. 

Daí lembrei do Docker :)

Bastou criar um container com os pacotes de compilação necessários como gcc, g++ e rpmbuild.  Mas o repositório está no laptop, que roda Ubuntu.  Como compilar?  Como acessar os dados?

Primeiramente criei um usuário no container Docker com mesmo UID e GID que o meu, pra não criar tudo como root.  Em seguida chamei o Docker com parâmetros pra usar meu filesystem:

helio@laptop:~$ docker run -it -v /home/helio/OpenSAF:/opensaf --user=helio -w /opensaf susebuilder4 ./configure

e pronto!  Binários compilados num ambiente que suporta LSB.  Docker mapeia meu diretório local "/home/helio/OpenSAF" como "/opensaf" no container.  Inicia como usuário "helio" dentro do diretório "/opensaf" e roda o comando "./configure".  E pronto.  Quando termina o comando, o container desaparece.

Sim, saem lágrimas dos olhos de tão lindo.

Docker permite isso.  Imagine então rodar um ambiente virtual com servidor web ou qualquer outra aplicação.  Uma vez terminada, some o container.  Quer aumentar capacidade?  Só criar outro container.  Eu não comentei muito, mas é possível mapear portas locais pra portas internas do container, além de rodar o próprio como daemon.

Docker é um monstro de tão bom.  Não é uma baleia, mas um Moby Docker!  Vale testar.

Compilando kernel Linux em Debian e Ubuntu

Categoria: Linux Publicado: Quarta, 10 Junho 2015 Escrito por Helio Loureiro

Ainda hoje muita gente mostra supresa quando digo que estou rodando um kernel recém lançado em meu sistema.  Apesar de quase todo mundo saber que Linux é o kernel apenas, uma parte do sistema operacional, pouca gente compila seu próprio kernel. E isso é uma coisa bastante simples com Debian e Ubuntu, ou qualquer outro sistema baseado neles.

Também vejo pessoas distribuindo o kernel em forma de download em sites como 4share, mega, etc.  É legal contribuir com comunidade, mas distribuir um kernel assim, a parte mais vital do sistema, dá brecha de segurança pra que alguém insira um malware ali.  Então evite fazer isso.  E compile seu próprio kernel.

O primeiro passo é ter o código fonte do Linux.  Depois que passou a utlizar o git pra controle de versão (e muito mais que isso), eu também passei a usar o mesmo pra sincronizar meus fontes.  No diretório "/usr/src", como root, crie o repositório git local da seguinte forma:

root@jessie:src# git clone https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

Não é um processo rápido.  O sistema vai baixar mais de 1 GB de arquivos no diretório "/usr/src/linux-stable".

Antes de botar a mão na massa, crie um novo "branch" com a versão que irá compilar.  É possível ver as versões disponíveis pelo comando "git tag -l".  No meu caso eu usei a versão v4.1-rc7.  Então a coisa toda pra listar e criar seu "branch" fica assim:

root@jessie:linux-stable# git tag -l | grep v4.1 
root@jessie:linux-stable# git checkout -b v4.1-rc7 tags/v4.1-rc7

O próximo passo é criar uma configuração de kernel antes de compilar.  Em geral eu copio o arquivo "/root/config-<minha versão corrente>".  Se quiser fazer isso, o comando correto é: 

root@jessie:linux-stable# cp /boot/config-$(uname -r) .

Existem outras maneiras de configurar o kernel, como usando o comando "make menuconfig" ou "make xconfig", entre outros.  Mas é preciso saber exatamente o que se quer do kernel pra configurar o que se realmente deseja.  Uma tarefa não muito fácil pras primeiras compilações.

O passo seguinte é instalar um pacote chamado "kernel-package".  Esse pacote é que faz toda a mágica da compilação e geração de pacotes pra você.  Isso mesmo: ao final do processo terá um kernel seu num arquivo .deb.  Eu já usei isso muito pra compilar em uma máquina e instalar em várias outras.  Voltando ao pacote, instale usado "apt-get", "apt" (novíssimo), ou "aptitude".

root@jessie:linux-stable# apt install kernel-package

O passo seguinte é chamar o kernel-package pra criar o kernel.  Eu pessoalmente uso da seguinte forma:

root@jessie:linux-stable# make-kpkg --initrd --append-to-version "-helio" --bzimage --revision 1 -j 4 kernel_image

O comando passado e os parâmetros são:

  • make-kpkg: é o comando instalado pelo pacote kernel-package.
  • --initrd: criar um sistema de boot initrd (a maioria dos sistema usa).
  • --append-to-version "-helio": pra deixar seu kernel com a sua "cara".  Vai aparecer algo como 4.1.0-rc7-helio na versão dele.
  • --bzimage: criar um kernel comprimido no formato bz.
  • --revision 1: revisão do pacote que será gerado.
  • -j 4: quantas CPUs serão usadas durante a compilação.  Se sua máquina tem múltiplos cores como a minha, basta colocar esse número.  Se não tem ou não sabe, não use esse parâmetro.
  • kernel_image: é o que diz pro kernel-package pra gerar só o pacote .deb do linux-image.  Pode-se criar outros pacotes como source, headers, etc.

Ao iniciar a compilação, o sistema passará por uma etapa de revisão da configuração que foi definida anteriormente.  Todo opção nova passará por uma pergunta se deve ou não ser incluída, ou ficar como módulo (pra ser carregado dinamicamente).  Toda pergunta já vem com alguma sugestão de resposta.  Em geral essa é a melhor opção a menos que realmente saiba o que aquela configuração significa.

Passada essa etapa, pode ir pegar um café.  Um café?  Melhor um bule inteiro.  E pode ir assistir ao último episódio de Game of Thrones que a compilação demora um pouco.

Uma vez terminada, se não tiver nenhum erro, será gerado um pacote com o formato "/usr/src/linux-image-<versão do kernel><nome que você personalizou>_<revisão>_<arquitetura da máquina>.deb".  No meu caso foi o pacote "/usr/src/linux-image-4.1.0-rc7-helio_1_amd64.deb".  Basta instalar e rebootar o computador pra testar a nova versão.

root@jessie:linux-stable# cd ..
root@jessie:linux-stable# dpkg -i linux-image-4.1.0-rc7-helio_1_amd64.deb
root@jessie:linux-stable# reboot

Se por acaso alguma coisa der errado, basta segurar o <Shift> ou <Esc> na inicialização da máquina, antes de carregar o Grub, pra poder ver o menu do mesmo.  Em seguida escolher o kernel que se estava rodando antes e inicializar por ele.  Depois basta remover o kernel criado, algo que e facilitado pela geração do pacote .deb.

root@jessie:linux-stable# dpkg -r linux-image-4.1.0-rc7-helio

Se for compilar o mesmo kernel, mas com opções de configuração diferentes, pode usar outra revisão.  Aliás incrementar a mesma.  Isso aparecerá no pacote gerado, mas não no kernel.

Boa compilação e boa diversão :)

Vírus em Linux

Categoria: Linux Publicado: Domingo, 01 Março 2015 Escrito por Helio Loureiro

Vírus em LinuxTem sido bastante difícil pra mim manter meu site atualizado, e não estou conseguindo manter meu ritmo de ao menos 1 post por semana.  Sinal de trabalho duro em outras coisas.

Estava pra comentar sobre esse assunto espinhoso, dos vírus pra Linux, faz um certo tempo.  Ao menos desde o início do ano.  Mas... enfim consegui um momento livre pra eu poder fazer isso.

A pergunta que surge de tempos em tempos é clara: EXISTEM VÍRUS PRA LINUX?

As respostas variam.  Defensores de Windows dizem que com toda certeza existem.  Mostram receitas esotéricas sobre como isso é possível e sempre voltam com a famosa frase "nenhum sistema é infalível", ou algo parecido com isso.

Os defensores de Linux, eu me incluo nesse grupo, dizem que é impossível.  Linux não é Windows.  Não foi feito sobre a mesma plataforma furada da Microsoft, que é cheia de buracos, e até provavelmente com alguns toques da NSA pra ajudar.  Se o usuário do Linux tem algum problema, o motivo é que não sabe atualizar sua distro.

Mas isso não explica a quantidade de problemas que têm aparecido sobre malwares em plataformas Linux, inclusive Android.

 

O problema é o windows.  Não que o windows tenha criado uma geração de vírus, mas o windows cunhou fortemente o conceito errado de que tudo é vírus.  Todo problema, malware, tudo é vírus.  E também foi graças ao windows que o conceito "se não funcionar, reinstala, se está lento, reinstala, e se quer mudar o wm, reinstala" se fortaleceu.  Isso se faz bem claro nos usuários que, pra trocar o Unity no Ubuntu, reinstalam o sistema inteiro.  Em geral com alguma refisefuqui.

Vírus é um pedaço de código que altera binários ou arquivos, e que se executa cada vez que esse programa é chamado ou aberto, no caso de arquivos.

Claramente isso não é possível no Linux por um simples motivo: quem executa o programa é o usuário e quem é o "dono" do binário é em geral o root.

Mas os problemas existem.  E muitos.  Existem os usuários que teimam em trabalhar como root no sistema, pra "facilitar as coisas".  Em geral os mesmos que reinstalam os sistema inteiro pra apenas trocar o wm (window manager).  Existem também os "programas de terceiros", como o plugin flashplayer, que não recebem as devidas atualizações de segurança.  Felizmente esses "programas de terceiros" não causam danos ao sistema como um todo, mas infelizmente podem fazer estrago o suficiente com o usuário, como permitir que suas credenciais de banco sejam roubadas.  Basta ver os recentes problemas do Java da Oracle.  Recentes?  Melhor dizer "contínuos".

E dá pra viver sem esses "aplicativos de terceiros"?  Até dá, mas não é muito fácil.  Alternativas existem, como pepperflashplugin ao invés do flash da Adobe, não usar acrobat reader ou seu plugin, mas os modos nativos do Firefox e do Chrome/Chromium pra renderizar pdf, etc.  O problema não são os "aplicativos de terceiros", mas se esses terceiros tratam os usuários de Linux com respeito, atualizando a cada falha encontrada.  Um bom exemplo dessa prática é o "steam", de jogos.

O problema então é o usuário, sempre?

Não.  Novamente o problema vem do windows.  Ou melhor, da idéia de vírus que veio com o uso do windows.  Quando discutimos o conceito de vírus, sempre nos vem a imagem de um desktop.  Daí os argumentos de problemas de segurança no Linux são apenas falta de atualização.  Isso não é verdade.

O outro lado do problema apareceu bem recentemente durante os ataques de DDoS do grupo LizzardSquad contra as redes de jogos PSN e Xbox Live.

Lizard Squad used hacked routers to take down Xbox Live and PlayStation Network

Foram usados roteadores caseiros, desses que usamos pra ter acesso wi-fi as nossas redes dentro de casa.  O artigo não diz, mas acredito que câmeras IPs também foram usadas.  

Esse tipo de problema não é novidade.  Foi discutido durante um dos YSTS, acho que o de 2013 que participei.  fabricantes, em geral na China, criam seus produtos pra rodar Linux, mas não dão nenhuma manutenção.  São sistemas customizados a ponto de ser impossível de rodar uma alternativa como dd-wrt/open-wrt. Esses sistemas rodam kernels Linux muito, mas muito velhos.  Daí que as explorações de vulnerabilidades, não vírus, ficam fáceis.  Nesse ponto temos de dar o braço a torcer pros usuários de windows.  Defender Linux nessas condições é quase como apontar o dedo pras máquinas windows comprometidas que rodam a versão XP.  O agravante é que o usuário se torna refém do fabricante, pois diferente dos computadores, esses sistemas embutidos não permitem que qualquer um atualize como quer, quando quiser, com a distro que mais gostar.

Então da próxima vez que ler sobre "vírus pra Linux", antes de cair na gargalhada, pense nesses roteadores e câmeras IPs.  Pense se esses sistemas rodando um Linux 2.4.20 não pode ter sua segurança facilmente comprometida.  Depois lembre que Windows, até hoje, pode ser comprometido acessando uma página web.  Foi corrigido?  Espere algumas semanas que sempre aparece de novo.

Ah... o windows...

Swapless Linux

Categoria: Linux Publicado: Sexta, 09 Janeiro 2015 Escrito por Helio Loureiro

Começando 2015, todos se lembram de como foi 2014.  Então resolvi escrever com um artigo sobre memória :)

Durante umas das discussões no grupo SOSLinux, alguém postou que já não usava Linux com swap fazia um tempo.  Nos meus velhos conceitos Unix adquiridos no século passado isso era algo inconcebível.  Uma heresia.  Um motivo pra receber um belo dum RTFM.

Esse é o problema de ter "aquela mesma velha opinião formada sobre tudo", como dizia Raul Seixas.  As coisas mudam.  Os sistemas evoluem.  Aquela recomendação de sempre se ter swap, e com fórmulas mágicas sobre seu tamanho, são coisas do passado, de uma era em que Linux era pra servidores e desktops.  Agora Linux está em todo lugar.  Na minha TV, no meu telefone, no meu tablet, e vai saber mais onde.  Talvez já esteja até no meu café e eu ainda não saiba.

Mas o fato é que naquela época a idéia era que as máquinas seriam cada vez maiores, mais potentes, mais gigantes, mais mais, muito mais.  Na verdade até são.  Mas aconteceu um fato interessante: o cloud.  Esse conceito permitiu uma forma de computação mais distribuída, com vários pequenos computadores ao invés de somente um maior.  E esse conceito foi se espalhando.  Se pensarmos hoje em dia nos celulares, eles são uma extensão computacional de algo que roda num datacenter.  Temos uma parte do aplicativo rodando localmente, e outra parte na nuvem.

Nesse novo paradigma, não é preciso tanto swap quanto antes.  Meu laptop tem 8 GB de RAM (tinha 12 GB com um pente extra de 4 GB que comprei no Dealextreme, mas o danado teima em dar problema de acesso e travar), mais que suficiente pra muita coisa.

Então resolvi experimentar.

Desabilitei o swap (swapoff /dev/mapper/vg-swap) e comentar a linha que o habilitava durante o boot no /etc/fstab.  E funcionou.  Mas bastou abrir chrome, firefox, thunderbird e eclipse pra coisa ficar feia (claro que a culpa é do java).

root@elx3030vlm-78:vm# head -16 /proc/meminfo 
MemTotal:        7926776 kB
MemFree:          218640 kB
MemAvailable:     889676 kB
Buffers:           57568 kB
Cached:           750036 kB
SwapCached:            0 kB
Active:          6672176 kB
Inactive:         404504 kB
Active(anon):    6282356 kB
Inactive(anon):    55548 kB
Active(file):     389820 kB
Inactive(file):   348956 kB
Unevictable:       65852 kB
Mlocked:           65852 kB
SwapTotal:             0 kB
SwapFree:              0 kB

Quando chega próximo do limite de memória, eu simplesmente tenho de aguardar o kernel decidir matar alguma coisa pra eu conseguir mandar um comando.  Até fiz um vídeo pra mostrar a situação.

{youtube}ga8lG2xE7wc{/youtube}

Nessas ocasiões a carga do sistema vai às alturas, provavelmente por troca de contexto de processos no kernel, tentando achar memória onde não tem.

Quando isso acontece, uma mudança do ambiente gráfico pro console e um reinicio do mesmo resolve.  Mas é chato.

Esses são os load averages que consegui enquanto gerava o vídeo acima:

 12:51:51 up 21:12,  6 users,  load average: 36.61, 59.21, 75.31
 13:01:24 up 21:21,  6 users,  load average: 57.21, 51.78, 61.71
 13:29:59 up 21:50,  6 users,  load average: 110.99, 122.08, 107.70

Então melhor com swap?  Não é tanto assim.  O sistema evoluiu, mas o problema de gerenciamento de memória é coisa do Linux.  Com swap esse tipo de problema também acontece, só demora mais.  Eu já tinha visto isso justamente com criação de vídeo no kdenlive.  Tinha um bug no melt, possivelmente um memory leak, que ia consumindo toda a memória.  Travava?  Não, mas tinha de aguardar o kernel matar o melt pra conseguir voltar.  Isso levava de 4 a 6 horas.  Usando somente RAM acontece o mesmo, mas é mais rápido, por volta de 20 ou 30 minutos.

Eu tentei achar alguma referência de tunning pra ajudar.

Memory Management Approach for Swapless Embedded Systems

When Linux Runs Out of Memory

http://linux-mm.org/LinuxMMDocumentation

O problema é que a maioria das informações são antigas.  No kernel que estou usando, 3.17.7, não tem esses parâmetros.  Mas eu tentei melhorar a responsividades alterando algumas coisas:

vm.laptop-mode = 1
vm.memory_failure_early_kill = 1
vm.memory_failure_recovery = 1

O resultado foi bastante satisfatório e agora o sistema tem estado mais responsivo durante alta carga que exige alocação de memória.  E com mensagens interessantes vindas do kernel.

Out of memory: Kill process 24223 (chromium-browse) score 332 or sacrifice child
Killed process 24223 (chromium-browse) total-vm:1360048kB, anon-rss:242548kB, file-rss:15632kB

Gosto de um sistema que exige sacrifícios.

Removendo um arquivo -C

Categoria: Linux Publicado: Sexta, 21 Novembro 2014 Escrito por Helio Loureiro

Isso mesmo.  Olhando meus diretórios pra começar um backup, percebi que criei um arquivo com nome "-C".  Provavelmente resultando de alguma comando errado.

O que fazer nesse caso?  Em geral comandos como "rm" e "mv" não funcionam pois interpretam o "-C" como uma opção do comando, não como arquivo.

Existem várias formas de resolver isso, inclusive algumas mais fáceis via interface gráfica usando nautilus/dolphin ou algo do gênero.  Mas vou mostrar a "forma UNIX" de resolver isso.

Primeiramente, onde está o danado do arquivo?

helio@linux:home$ ls
backup -C helio fisl lost+found support

No caso estava no meu diretório "/home".  E o que era o arquivo?

helio@linux$ home# ls -l
total 646124
drwxr-xr-x 2 root root 4096 Nov 21 09:41 backup
-rw-r--r-- 1 root root 661555200 Oct 9 12:05 -C
drwxr-xr-x 367 helio linux 36864 Nov 21 09:43 helio
drwxr-xr-x 6 fisl fisl 4096 Mar 5 2014 fisl
drwx------ 2 root root 16384 Nov 16 2013 lost+found
drwxr-xr-x 5 support admin 4096 May 17 2013 support

Agora vem o truque.  Cada arquivo criado no seu filesystem tem junto um número de i-node, que é onde ele foi efetivamente gravado no disco.  É possível usar a opção "-i" do comando "ls" pra verificar cada número de i-node de cada arquivo do diretório, seja um arquivo, seja um diretório, ou seja qualquer outra coisa (em Unix, tudo é arquivo).

root@linux:home# ls -i
15335425 backup 4741 -C 16252929 helio 14942209 fisl 11 lost+found 15466497 support

Verificado qual o número do i-node, 4741, agora é usar o comando "find" com opção de "-inum" pra mexer nesse arquivo, junto com um "-exec".  Na opção "-exec", o arquivo encontrado é substituído pelo "{}", que é como se fosse uma variável com o que foi encontrado pelo parâmetros anteriores, no caso o "-inum".  

Então basta usar isso pra renomear o arquivo pra qualquer outro nome.

root@linux:home# find . -maxdepth 1 -inum 4741 -exec mv {} arquivo_alien \;

Verificando...

root@linux:home# ls
backup helio fisl lost+found support arquivo_alien

Agora descobrindo o que é esse arquivo.

root@linux:home# file arquivo_alien
arquivo_alien: POSIX tar archive (GNU)
root@linux:home# mv arquivo_alien arquivo_alien.tar
root@linux:home# tar tvf arquivo_alien.tar
drwxr-xr-x root/root 0 2014-10-09 12:05 home/
drwxr-xr-x fisl/fisl 0 2014-03-05 10:16 home/fisl/
drwxr-xr-x fisl/fisl 0 2014-03-05 10:16 home/fisl/.purple/
-rw-r--r-- fisl/fisl 173 2014-03-05 10:16 home/fisl/.purple/blist.xml
drwxr-xr-x fisl/fisl 0 2013-07-04 22:21 home/fisl/.purple/certificates/

Realmente um arquivo do tipo tar.  Provavelmente de algum backup que tentei fazer e passei a opção de forma errado.  Sem stress e problema resolvido.

root@linux:home# rm arquivo_alien.tar