Criando um box para o Vagrant

13 de nov de 2016 - Por Paulo Dias

O Vagrant é um projeto que permite gerenciar ambientes virtuais de forma simples e eficiente. Ele possui suporte as principais soluções de virtualização e também para várias ferramentas de provisionamento, como Puppet e Chef·

O Vagrant empacota as máquinas virtuais em boxes que podem ser criados e depois disponibilizados no site oficial do projeto. Nesse artigo, quero mostrar como criar e disponibilizar uma box para o Vagrant. A maneira mais simples de criar um box é a partir de um box já existente, mas vou optar por criar um box do zero.

O site do Vagrant já possui boxes para as distribuições GNU/Linux mais conhecidas... Então, para criar algo diferente, vou utilizar uma distribuição menos conhecida, o Slitaz. Trata-se de uma distribuição independente( não é baseada em outra distribuição ) que na versão mais completa, com ambiente gráfico e outros programas de uso geral, cabe em uma imagem .ISO com menos de 50MB. O trabalho realizado pelos desenvolvedores do Slitaz é excelente e pode ser conferido em detalhes no site http://www.slitaz.org/en/.

Como a ideia é criar um box para o Vagrant, vou utilizar o sabor base do Slitaz que possui apenas o ambiente em modo texto e, consequentemente, uma imagem .ISO ainda menor. O download pode ser feito nesse endereço http://mirror.slitaz.org/iso/4.0/flavors/.

Para configurar o Slitaz como um box, é necessário instalá-lo em uma máquina virtual, instalar um conjunto de pacotes e configurar alguns arquivos. Para iniciar, é necessário ter o Vagrant e o VirtualBox instalados na máquina física. No Debian Jessie e em distribuições Debian-like, a instalação pode ser feita com o seguinte comando:

 
sudo apt-get install vagrant virtualbox
 

Feito isso, basta criar um máquina no VirtualBox e iniciar a imagem do Slitaz. O processo de boot é extremamente rápido, serão feitas algumas perguntas para localização do ambiente e o sistema já está pronto para ser utilizado. O usuário 'root' por padrão usa a senha 'root'.

Por enquanto o Slitaz está rodando no modo live a partir da imagem de CD, para realizar a instalação, o primeiro passo é particionar o HD. Isso pode ser feito com o comando fdisk, assim:

Observação: Os próximos comandos devem ser executados na máquina virtual do Slitaz.

 
fdisk /dev/sda

No fdisk pressionando 'm' as opções disponíveis são listadas. Para criar um partição primaria, pressione 'n', depois 'p', escolha o número para partição( 1 ), escolha o inicio da partição( 1 ) e o tamanho da partição( +8000M ). Para sair do fdsik, pressione 'w'.

Depois de criar a partição, adicione um sistema de arquivo com o comando:

 
mkfs.ext4 /dev/sda1

O próximo passo é copiar os arquivos do Slitaz para a partição do HD. A partição e o CD do Slitaz( a imagem .ISO que está no VirtualBox ) devem ser montadas com os comandos:

 
mount /dev/sda1 /mnt

mount /dev/cdrom /media/cdrom

Então, para copiar o kernel, faça:

 
mkdir /mnt/boot/

cp -a /dev/cdrom/boot/vmlinuz* /mnt/boot/

Depois, copie e descompacte o filesystem :


cp /media/cdrom/boot/rootfs.gz /mnt/

cd /mnt/

unlzma < rootfs.gz | cpio -id 

rm rootfs.gz init

Feito isso, o Slitaz já está instalado, mas antes de continuar ainda é necessário instalar o GRUB ( a primeira versão, também chamado de GRUB legacy ). Execute o comando:


grub-install --root-directory=/mnt/ /dev/sda 

E crie o arquivo de configuração /mnt/boot/grub/menu.lst com o seguinte conteúdo:


timeout 5

default 0

title Slitaz
     root( hd0, 0 )
     kernel /boot/vmlinuz-2.6.37-slitaz root=/dev/sda1 vga=normal

Observação: O root( hd0, 0 ) é referente ao primeiro HD e a primeira partição, ou seja, /dev/sda e /dev/sda1. Se fosse a primeira partição do segundo HD seria root( hd1, 0 ).

O Slitaz e o GRUB estão instalados, retire a imagem do Slitaz do virtualBox e reinicie o sistema com o comando:


reboot

Boot em 4 segundos :O

Com o sistema instalado, é possível instalar os pacotes necessários para o Slitaz ser um box do Vagrant:


tazpkg recharge

tazpkg get-install sudo
tazpkg get-install openssh
tazpkg get-install linux-api-headers
tazpkg get-install linux-module-headers
tazpkg get-install dkms
tazpkg get-install bzip2
tazpkg get-install wget
tazpkg get-install bash

Durante a instalação do bash, o sistema vai perguntar se o sh deve ser um link para o bash, certifique-se de responder yes.

Depois, para seguir o padrão dos boxes do Vagrant, é necessário ter um usuário 'vagrant' com senha 'vagrant' e também alterar a senha do usuário 'root' para 'vagrant':


adduser vagrant

passwd

O Vagrant conecta no sistema usando SSH sem senha através do sistema de chaves, para que isso funcione, é preciso baixar a chave publica para o usuário 'vagrant'.


mkdir /home/vagrant/.ssh/

wget --no-check-certificate https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub -O /home/vagrant/.ssh/authorized_keys

chown vagrant:vagrant /home/vagrant/.ssh/ -R

chmod 0700 /home/vagrant/.ssh/
chmod 0600 /home/vagrant/.ssh/authorized_keys

O usuário 'vagrant' também precisa poder usar o sudo sem senha, isso pode ser configurado com o comando visudo adicionando a linha:


vagrant ALL=(ALL) NOPASSWD: ALL

O próximo passo é instalar os adicionais de convidado do VirtualBox, adicione a imagem de CD na máquina virtual e execute esses comandos para realizar a instalação:


mount /dev/cdrom /media/cdrom

sh /media/cdrom/VBoxLinuxAddtions.run

Feito isso, o sistema já está quase pronto para ser um box, mas antes de terminar é importante adicionar a seguinte linha, sugerida pela equipe do Vagrant, no arquivo /etc/ssh/sshd_config:


UseDNS no

E por último, como o Vagrant utiliza apenas o comando shutdown -h now para desligar o sistema, e esse comando não está presente, de forma nativa no Slitaz( ele usa o poweroff, halt e reboot ), é necessário criar uma alternativa... Um jeito simples, é criar um shell script /sbin/shutdown com o seguinte conteúdo:


#!/bin/bash

if [ $1 = '-h' -a $2 = 'now'] ; then

     poweroff;
     exit 0;

fi

echo 'Only shutdown -h now is implemented';
exit 1;


Observação: Use o comando chmod para dar permissão de execução para o script.

Pronto, com isso, o sistema já está configurado para ser um box do Vagrant. Para terminar, desligue a máquina virtual e na máquina física execute o seguinte comando:


vagrant package --base nome_vm_slitaz

Observação: Substitua nome_vm_slitaz pelo nome da máquina do Slitaz que você criou no VirtualBox.

Com isso, foi criado o box do Slitaz com o nome 'package.box'. Para testar, utilize os seguintes comandos:


vagrant box add slitaz package.box

vagrant init slitaz

vagrant up

Depois de testar o seu box, se quiser compartilhar, basta criar uma conta nesse link https://atlas.hashicorp.com/account/new.

Então é isso, qualquer dúvida, deixe um comentário e se quiser baixar o meu box do Slitaz, acesse: https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=p4ulodi4s

Leia mais

Nagios Core no Ubuntu 14.04 - Parte 1

7 de jul de 2016 - Por Paulo Dias

Oi, tudo bem?

Hoje vou iniciar uma serie de artigos sobre como instalar e configurar o Nagios Core através dos repositórios do Ubuntu 14.04. O Nagios é um sistema de monitoramento de rede de código aberto distribuído sob a licença GPL. Ele pode monitorar hosts e serviços, alertando quando ocorrerem problemas e também quando os problemas são resolvidos.

Nesse artigo, quero mostrar como instalar, administrar usuários e monitorar hosts ativos na rede. Para isso, o primeiro passo é executar a instalação com o seguinte comando:

 
sudo apt-get install nagios3 nagios-plugins-extra
 

Durante a instalação será necessário definir uma senha para o usuário padrão do Nagios. O usuário é o nagiosadmin, escolha a senha conforme a sua vontade.

Feito isso, o Nagios já vai estar instalado e funcionando... Utilize o seu navegador( use sempre o firefox :) para acessar a máquina onde o Nagios foi instalado. A URL segue o seguinte padrão: http://ip.da.maquina/nagios3.

A seguinte janela vai requisitar os dados de autenticação:

Forneça o usuário nagiosadmin e a senha que foi cadastrada durante a instalação. Se tudo ocorreu normalmente, uma interface semelhante a essa será exibida:

Com o Nagios instalado é possível criar novos usuários para ter acesso a essa interface WEB. Para isso, utilize o seguinte comando:

 
sudo htpasswd /etc/nagios3/htpasswd.users paulo

Dessa forma, o usuário paulo vai ter acesso a interface WEB do Nagios, mas ainda não vai ter permissões para acessar algumas páginas. Isso ocorre devido as permissões que estão configuradas no arquivo /etc/nagios3/cgi.cfg. Para dar as mesmas permissões do usuário nagiosadmin para o novo usuário, use os seguintes comandos:

 
sudo mv /etc/nagios3/cgi.cfg /etc/nagios3/cgi.bkp

sudo cat /etc/nagios3/cgi.bkp | sed s/=nagiosadmin/=nagiosadmin,paulo/g > /etc/nagios3/cgi.cfg

sudo service nagios3 restart

Obs.: Substitua paulo pelo nome do seu usuário.

Depois de configurar outro usuário com todas as permissões necessárias, recomendo remover o usuário nagiosadmin. Para fazer isso, use o comando:

 
sudo htpasswd -D /etc/nagios3/htpasswd.users nagiosadmin

Para configurar um monitoramento é necessário criar um arquivo dentro da pasta /etc/nagios3/conf.d. Todos os arquivos com a extensão .cfg no interior dessa pasta( e sub-pastas ) serão analisados pelo Nagios. A instalação do Nagios já deixou alguns arquivos preparados. No meu Ubuntu existem os seguintes arquivos:

 
extinfo_nagios2.cfg
generic-host_nagios2.cfg
generic-service_nagios2.cfg
hostgroups_nagios2.cfg
localhost_nagios2.cfg
services_nagios2.cfg
timeperiods_nagios2.cfg

Os arquivos generic-host_nagios2.cfg e generic-service_nagios2.cfg são templates que podem ser utilizados para criar novos monitoramentos de forma simples. Para que o Nagios monitore se um equipamento está conectado na rede( através do protocolo ICMP ) crie o arquivo /etc/nagios3/conf.d/equipamento.cfg com o seguinte conteúdo:

 
define host{
use                 generic-host
host_name           equipamento
alias               equipamento
address             192.168.0.108
}

define service{
use                   generic-service
host_name             equipamento
service_description   PING
check_command         check_ping!550.0,10%!600.0,20%
}

Observação.: Altere o campo address com o endereço IP do seu equipamento

Acessando o link Map no menu da esquerda da interface WEB do Nagios será carregada uma tela semelhante a essa:

Com essa configuração o Nagios vai monitorar e sinalizar na interface WEB se o equipamento for desconectado.

Perceba que o novo monitoramento está utilizando um ícone com o simbolo de interrogação( ? ), mas é possível alterar esse simbolo por outro que identifique o equipamento de uma forma mais adequada. Altere o arquivo /etc/nagios3/conf.d/equipamento.cfg com o seguinte conteúdo:

 
define host{
use                 generic-host
host_name           equipamento
alias               equipamento
address             192.168.0.108
}

define service{
use                   generic-service
host_name             equipamento
service_description   PING
check_command         check_ping!550.0,10%!600.0,20%
}

define hostextinfo{
host_name       equipamento
icon_image      switch.png
icon_image_alt  equipamento
statusmap_image switch.png
}

Para que essa configuração tenha o efeito desejado é necessário colocar a imagem( no exemplo switch.png ) na seguinte pasta: /usr/share/nagios3/htdocs/images/logos/

A próxima imagem é de um sistema que já está em produção, veja como os ícones fornecem uma melhor visão da rede:

Veja que além dos ícones, que identificam os equipamentos, a forma como os equipamento foram organizados oferece um boa visualização dessa rede. Para conseguir esse efeito, é necessário alterar o arquivo /etc/nagios3/conf.d/equipamento.cfg e adicionar o atributo parents na definição do host. Veja:

 
define host{
use                 generic-host
host_name           equipamento
alias               equipamento
address             192.168.0.108
parents             localhost
}

define service{
use                   generic-service
host_name             equipamento
service_description   PING
check_command         check_ping!550.0,10%!600.0,20%
}

define hostextinfo{
host_name       equipamento
icon_image      switch.png
icon_image_alt  equipamento
statusmap_image switch.png
}

Veja a diferença na interface WEB do Nagios:

Dessa forma, fica evidente que o novo equipamento está ligado diretamente no localhost ( no servidor onde o Nagios está instalado ).

Obs.: No atributo parents é especificado o atributo host_name de outro equipamento.

Bom pessoal, esse artigo termina aqui, no próximo quero mostrar como configurar o postifix e receber alertas do Nagios por email. Obrigado e até mais...

Leia mais

Bitwise: Multiplicando números inteiros

2 de abr de 2016 - Por Paulo Dias

Nesse artigo quero mostrar como realizar a multiplicação de números inteiros utilizando apenas os operadores de bitwise da linguagem Java. Esses operadores realizam alterações diretamente nos bits e são extremamente rápidos.

A ideia para esse artigo surgiu de um exercício de lógica de programação que pedia para implementar um método de multiplicação de inteiros sem utilizar o operador da linguagem( * ). Esse é um exercício bem simples e a implementação mais comum pode ser escrita da seguinte maneira:

 
    public static int multiplicar( int numero1, int numero2 ) {
    
        int resultado = 0;
        
        for( int i = 0; i < numero1; i++ )
            resultado += numero2;
        
        return resultado;
    }
 

Esse método funciona, mas é lento... Utilizando operadores bitwise é possível implementar um método bem mais eficiente...

Apesar de oferecer maior desempenho, utilizar operadores de bitwise é mais trabalhoso e exige um pouco mais de prática. Por isso, é fortemente recomendado, antes de continuar, que seja feita a leitura desse outro artigo: http://www.prminformatica.com.br/2014/01/bitwise-escovar-bits.html.

O algoritmo que vou utilizar é similar ao método de multiplicação ensinado nas escolas. Ele é apresentado em detalhes nesse link http://www.exploringbinary.com/binary-multiplication/. Também sugiro realizar a leitura desse artigo antes de continuar...

Feita a introdução, o primeiro passo é implementar um método auxiliar que seja capaz de realizar adição dos bits. Basicamente, a adição de binários pode ser realizada com o operador xor ( em Java ^ ). Veja:

0 + 0=0
1 + 0=1
0 + 1=1
1 + 1=0 ( e vai 1) == 10

Perceba que exceto pelo último caso de teste, 1 + 1 = 10, o operador xor devolve o resultado correto. Assim sendo, para realizar a adição é possível usar o operador xor e em seguida identificar se existe o caso de teste problemático( 1 + 1 = 10 ). Se existir, é necessário utilizar novamente o xor para adicionar o 1 do 'vai 1'. Obviamente, essa segunda operação com o xor também pode ter o caso de teste problemático... Então, é necessário refazer o teste e repetir a operação até que isso não ocorra ( uma boa oportunidade para utilizar recursividade ).

Para identificar se existe o caso de teste 1 + 1 = 10 basta utilizar o operador and ( em Java & ) com os 2 números. Veja:

0 & 0=0
1 & 0=0
0 & 1=0
1 & 1=1

Assim, se o resultado da operação and entre os 2 números for igual a zero, o caso de teste problemático não existe. Senão, o caso de teste problemático existe.

Veja uma implementação possível para o método somar:

 
    public static int somar(int numero1, int numero2) {
        
        if(numero2 == 0)
            return numero1;

        return somar( numero1 ^ numero2, (numero1 & numero2) << 1);
    }
 

Observação: o << 1 coloca, se existir, o 1 na próxima posição a esquerda de onde ocorreu o caso de teste problemático. ( O 1 deve ser adicionado na próxima coluna da esquerda )

Com o método de adição pronto, já é possível iniciar a construção de um método para realizar a multiplicação. A multiplicação de bits pode ser realizada com o operador and, mas será necessário pegar o primeiro bit do número1 e realizar a operação and com cada um dos bits do número2 e em seguida pegar o segundo bit do número1 e realizar a operação and com cada um dos bits do número2 e assim por diante... ( Veja o link que explica o algoritmo de multiplicação )

Para pegar um bit especifico de uma variável é possível usar esse código:


int bitPosicao = ( numero & ( 0b1 << posicao ) ) >> posicao;

Nesse código, se o bit da posição escolhida for zero, bitPosicao recebe zero. Se o bit da posição escolhida for 1, bitPosicao recebe um valor diferente de zero.

Com isso, basta pegar os bits ( um do primeiro número e outro do segundo ), realizar a operação and, e armazenar o bit resultante em uma variável auxiliar de forma que ele ocupe a posição correta. Veja:


int numero1 = 0b1; //0000 0001 (apenas o primeiro byte)

int numero2 = 0b10; //0000 0010


int resultadoParcial = 0b0; //0000 0000


int posicaoBitNumero1 = 0;
            
int bitNumero1 = ( numero1 & ( 0b1 << posicaoBitNumero1 ) ) >> posicaoBitNumero1; // 0000 0001
                
  
int posicaoBitNumero2 = 0; 

int bitNumero2 = ( numero2 & ( 0b1 << posicaoBitNumero2 ) ) >> posicaoBitNumero2; // 0000 0000
                
//guarda o primeiro teste na posição do bitNumero2
resultadoParcial = resultadoParcial | ( ( bitNumero1 & bitNumero2 ) << posicaoBitNumero2 ); //  0000 0000


posicaoBitNumero2 = 1; //para pegar o segundo bit do numero2

bitNumero2 = ( numero2 & ( 0b1 << posicaoBitNumero2 ) ) >> posicaoBitNumero2; // 0000 0001
                
//guarda o segundo teste na posição do bitNumero2
resultadoParcial = resultadoParcial | ( ( bitNumero1 & bitNumero2 ) << posicaoBitNumero2 ); // 0000 0010

Nesse exemplo, pego o primeiro bit da variável numero1 e realizo a operação and com esse bit e cada um dos bits da variável numero2. Após cada teste é usada a posição do bit da variável numero2 para armazenar o bit resultante na variável resultadoParcial. Veja que a operação or( em Java | ) entre a variável resultadoParcial e o bit resultante da operação and entre a variável numero1 e a variável numero2 não altera os bits que foram armazenados anteriormente.

Com esse exemplo, já é possível ter uma ideia dos passos necessários, mas esse processo deve ser repetido para todos os bits das variáveis numero1 e numero2. Para isso, é necessário saber qual a quantidade de bits dessas variáveis( a quantidade é igual para ambas, as duas são do tipo int ).

Em Java não existe um operador semelhante ao sizeof do C, mas a quantidade de bits de cada tipo pode ser previamente verificada. Veja esse link: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. Utilizando esse link é possível afirmar que o tipo int têm 32 bits.

Assim sendo, é possível criar um for para pegar todos os bits da variável numero1 e um segundo for, aninhado no primeiro, para pegar todos os bits da variável numero2. Veja:


    public static int multiplicarBit(int numero1, int numero2) {

        int resultadoFinal = 0b0;

        for (int i = 0; i < 32; i++) {

            int resultadoParcial = 0b0;

            int bitNumero1 = (numero1 & (0b1 << i)) >> i;

            for (int j = 0; j < 32; j++) {

                int bitNumero2 = (numero2 & (0b1 << j)) >> j;

                resultadoParcial = resultadoParcial | ((bitNumero1 & bitNumero2) << j);
            }

            resultadoFinal = somar(resultadoFinal, (resultadoParcial << i));
        }

        return resultadoFinal;
    }

Observação: Assim, estão sendo calculados zeros que não têm significância( zeros à esquerda ). É possível usar alguns métodos específicos da classe Integer para evitar isso... Fica a dica :)

Para testar a eficiência desse método em comparação com o método de adições consecutivas criei o seguinte código :


package javaapplication1;

public class JavaApplication1 {

    public static int multiplicarSimples(int numero1, int numero2) {

        int resultado = 0;

        for (int i = 0; i < numero1; i++) {
            resultado += numero2;
        }

        return resultado;
    }

    public static int multiplicarBit(int numero1, int numero2) {

        int resultadoFinal = 0b0;

        for (int i = 0; i < 32; i++) {

            int resultadoParcial = 0b0;

            int bitNumero1 = (numero1 & (0b1 << i)) >> i;

            for (int j = 0; j < 32; j++) {

                int bitNumero2 = (numero2 & (0b1 << j)) >> j;

                resultadoParcial = resultadoParcial | ((bitNumero1 & bitNumero2) << j);
            }

            resultadoFinal = somar(resultadoFinal, (resultadoParcial << i));
        }

        return resultadoFinal;
    }

    public static int somar(int numero1, int numero2) {

        if (numero2 == 0) {
            return numero1;
        }

        return somar(numero1 ^ numero2, (numero1 & numero2) << 1);
    }

    public static void main(String[] args) {

        int numero1 = 732222;
        int numero2 = 345;

        long tempoInicial = System.currentTimeMillis();

        int resultado = multiplicarSimples( numero1, numero2 );

        long tempoFinal = System.currentTimeMillis();

        System.out.println( "Resultado simples = " + resultado + " tempo = " + (tempoFinal - tempoInicial) );

        tempoInicial = System.currentTimeMillis();

        resultado = multiplicarBit( numero1, numero2 );

        tempoFinal = System.currentTimeMillis();

        System.out.println( "Resultado bitwise = " + resultado + " tempo = " + (tempoFinal - tempoInicial) );
        
    }

}

Observação: Eu sei que existem formas melhores de comparar a eficiência desses códigos, mas, para esse exemplo, acredito que pegar a diferença de tempo é o suficiente.

Segue os testes realizados:


//teste 0
Numero1 = 732222
Numero2 = 345
Resultado simples = 252616590 tempo = 6
Resultado bitwise = 252616590 tempo = 0

//teste 1
Numero1 = 732222
Numero2 = 9
Resultado simples = 6589998 tempo = 5
Resultado bitwise = 6589998 tempo = 0

//teste 2
Numero1 = 86
Numero2 = 3
Resultado simples = 258 tempo = 0
Resultado bitwise = 258 tempo = 0

//teste 3 - o resultado foi maior que um int
Numero1 = 123456
Numero2 = 654321
Resultado simples = -824525248 tempo = 5
Resultado bitwise = -824525248 tempo = 0

Leia mais

LAMP: Linux, Apache, MYSQL e PHP

31 de out de 2015 - Por Paulo Dias

Oi, tudo bem?

Nesse artigo quero mostrar como instalar o Apache, o MYSQL e o PHP no Ubuntu. Para obter esse ambiente é comum utilizar o XAMPP ou alguma aplicação semelhante, mas quero mostrar como instalar cada um deles de forma individual usando os pacotes disponíveis nos repositórios da distribuição. Visto a popularidade das ferramentas que automatizam a instalação desse ambiente, pode parecer que a instalação de cada um desses pacotes seja uma tarefa complicada, mas no Ubuntu, e em qualquer outra distribuição GNU/Linux, esse processo é razoavelmente simples.

Para começar vou mostrar como instalar o servidor Apache. Para isso, execute os seguintes comandos:

 
sudo apt-get update

sudo apt-get install apache2
 

Se o Apache foi instalado corretamente, a seguinte página vai ser visualizada na URL http://localhost:

Teste Apache

Com o Apache instalado, o próximo é o MYSQL. A instalação desse pacote pode ser realizada com o seguinte comando:


sudo apt-get install mysql-server
 

Durante a instalação uma tela parecida com a seguinte irá solicitar uma senha para o usuário root do MYSQL.

Imagem exemplo da instalação MYSQL

Depois da instalação terminar, teste o MYSQL efetuando o login com o usuário root:


mysql -u root -p
 

O MYSQL solicitará a senha de root que foi definida na instalação. Após informá-la, você verá uma tela como a seguinte:

Imagem exemplo prompt do MYSQL

Observação: Para sair do prompt do MYSQL digite o comando quit.

Se foi possível realizar o login, o MYSQL está instalado corretamente. Porém, é possível acessa-lo apenas da máquina local, para permitir conexões externas é necessário criar o arquivo /etc/mysql/conf.d/allow_external.cnf. com o seguinte conteúdo:


[mysqld]
     bind-address = 0.0.0.0

Agora o Apache e o MYSQL já foram instalados, falta apenas o PHP. Para instala-lo utilize o seguinte comando:

sudo apt-get install php5 php5-mysql

Para testar a instalação do PHP crie o arquivo /var/www/html/teste.php com esse conteúdo:

phpinfo();

Depois, garanta que Apache pode executar o arquivo utilizando o comando:

sudo chmod 755 /var/www/html/teste.php

Se tudo deu certo, uma página semelhante a seguinte vai ser exibida na URL http://localhost/teste.php:

Imagem exemplo PHP

O PHP já está instalado, mas sua configuração padrão está com as mensagens de erro desabilitada. Assim sendo, se houver algum erro no código de um arquivo, você não será avisado. Esse é o comportamento esperado em um ambiente de produção, mas para um ambiente de desenvolvimento é impraticável. Para permitir a exibição de mensagens de erros no PHP é necessário alterar o arquivo /etc/php5/apache2/php.ini.

Nesse arquivo procure por :

display_errors = Off

e altere para:

display_errors = On

Depois de realizar a alteração, reinicie o Apache com o comando:

sudo /etc/init.d/apache2 restart

Feito isso, o PHP vai exibir as mensagens de erro. Faça um teste, altere o arquivo /var/www/html/teste.php com o seguinte conteúdo:

erro_phpinfo();

Pronto, você instalou e configurou o seu LAMP. Porém, ainda é possível adicionar várias bibliotecas para a instalação do PHP. Para verificar uma lista das bibliotecas disponíveis use o comando:

apt-cache search php5

Será exibida uma listagem parecida com essa:

libapache2-mod-php5 - linguagem de scripts imersa em HTML, roda no servidor (módulo Apache 2)
php5 - linguagem de script incorporável em HTML, lado servidor (metapacote)
php5-cgi - server-side, HTML-embedded scripting language (CGI binary)
php5-cli - command-line interpreter for the php5 scripting language
php5-common - arquivos comuns para pacotes construídos a partir do código fonte do php5
php5-curl - CURL module for php5
php5-dbg - Debug symbols for PHP5
php5-dev - Files for PHP5 module development
php5-gd - GD module for php5
php5-gmp - GMP module for php5
php5-json - JSON module for php5
php5-ldap - LDAP module for php5
php5-mysql - MySQL module for php5
php5-odbc - ODBC module for php5
php5-pgsql - PostgreSQL module for php5
php5-pspell - pspell module for php5
php5-readline - Readline module for php5
php5-recode - recode module for php5
php5-snmp - SNMP module for php5
php5-sqlite - SQLite module for php5
php5-tidy - tidy module for php5
php5-xmlrpc - XML-RPC module for php5
php5-xsl - XSL module for php5

Para saber mais sobre um pacote utilize o comando:

apt-cache show nome_pacote

Veja um exemplo:

apt-cache show php5-pgsql

Package: php5-pgsql
Priority: optional
Section: php
Installed-Size: 219
Maintainer: Ubuntu Developers 
Original-Maintainer: Debian PHP Maintainers 
Architecture: amd64
Source: php5
Version: 5.5.9+dfsg-1ubuntu4.14
Depends: libc6 (>= 2.14), libpq5 (>= 9.0~), phpapi-20121212, php5-common (= 5.5.9+dfsg-1ubuntu4.14), ucf
Pre-Depends: dpkg (>= 1.15.7.2~)
Filename: pool/main/p/php5/php5-pgsql_5.5.9+dfsg-1ubuntu4.14_amd64.deb
Size: 51590
MD5sum: 564b17207f9e6a57bd26991fb50891f7
SHA1: 06787910a6d2a0c5718bf140bbec3a1d335c2a12
SHA256: 555463b935011fd772b3b5a717b44513e0a660c71a32caeb186d06c1c9ffce7e
Description-pt_BR: PostgreSQL module for php5
 This package provides a module for PostgreSQL database connections
 directly from PHP scripts.  It also includes the pdo_pgsql module for use
 with the PHP Data Object extension.
 .
 PHP (acrônimo recursivo para PHP: Hypertext Preprocessor) é uma linguagem
 de script de código aberto e propósito geral amplamente utilizada que foi
 especialmente implementada para desenvolvimento web e pode ser embarcada
 dentro do HTML.
Description-md5: 25edec9b992444a2c1634b9545b31326
Homepage: http://www.php.net/
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu
Supported: 5y
...

Se quiser instalar alguns desses pacotes, use o comando:

sudo apt-get install nome_pacote1 nome_pacote2 ...

Veja o exemplo:

sudo apt-get install php5-pgsql php5-sqlite php5-ldap php5-json php5-gd
Leia mais

Inicializando imagem .ISO no GRUB2

23 de jul de 2015 - Por Paulo Dias

Oi, tudo bem? Hoje quero escrever sobre como inicializar uma imagem .ISO de uma distribuição GNU/Linux através do GRUB2.

Vou tentar explicar todo o procedimento necessário para ter uma imagem .ISO de qualquer distribuição GNU/Linux dando Boot através do GRUB2. Porém, antes de iniciar é importante já ter conhecimento básico sobre o funcionamento do GRUB2. Se você não está seguro sobre as caracteristicas do GRUB2, veja esse artigo que escrevi em 2013 http://www.prmjuniorblog.blogspot.com.br/2013/02/configurando-o-grub2-no-debian-squeeze.html.

Sabendo disso, o primeiro passo a ser realizado é verificar a localização de 2 arquivos dentro da imagem .ISO. Os arquivos são vmlinuz e initrd. Para verificar o conteúdo da imagem utilize algum utilitário do tipo desempacotador (ark). Veja um exemplo de uma imagem do Ubuntu Server:

imagem de exemplo do Ubuntu

É importante verificar porquê a localização e as extensões desses arquivos podem mudar dependendo da imagem .ISO. Por exemplo, veja a um imagem do KUbuntu Desktop:

imagem de exemplo do Kubuntu

Perceba pela imagem que para a .ISO do KUbuntu os arquivos vmlinuz e initrd estão dentro da pasta casper.

Sabendo a localização dos arquivos na imagem .ISO, crie uma pasta na raiz do seu sistema e coloque essa imagem dentro dela. Exemplo: /isos/kubuntu-14.04.2-desktop-amd64.iso .

sudo mkdir /isos
sudo mv kubuntu-14.04.2-desktop-amd64.iso /isos/
sudo chmod 755 /isos -R

Feito isso, crie o arquivo /etc/grub.d/99_isos com o seguinte conteúdo:

#!/bin/sh
exec tail -n +3 $0

menuentry "KUbuntu 14.04 ISO" {

        set iso="/isos/kubuntu-14.04.2-desktop-amd64.iso"
        loopback loop (hd0,5)$iso
        linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=$iso quiet splash
        initrd (loop)/casper/initrd.lz
}

Veja que vmlinuz, initrd e a pasta casper são referenciados algumas vezes. Faça as substituições conforme os dados da sua imagem .ISO .

Além disso, é necessário alterar a informação (hd0,5) conforme a sua situação. O hd0 faz referência ao primeiro HD( sda ) e 5 faz referência a 5ª partição desse HD( sda5 ). Altere essa informação conforme a partição onde a sua imagem .ISO estiver.

No artigo de 2013 sobre o GRUB2 eu escrevi sobre isso, mas é importante lembrar que o GRUB2 conta os HDs iniciando no zero( 0, 1, 2 ...) e as partições iniciando no 1 ( 1, 2, 3 ... ).

Depois de realizar todas as alterações necessárias, rode os comandos:

sudo chmod 755 /etc/grub.d/99_isos
sudo update-grub

Pronto reinicie o sistema e acesse alternativa correspondente a .ISO no menu do GRUB.

Eu criei esse artigo devido a uma dúvida que respondi no fórum Viva o Linux, veja: http://www.vivaolinux.com.br/topico/Desktops/Ubuntu-com-Isos/?pagina=1

Qualquer dúvida, deixe um comentário. Até mais...

Leia mais

Configuração de rede no Ubuntu 12.04 - Arquivos

19 de fev de 2015 - Por Paulo Dias

No GNU/Linux (quase)todos os arquivos de configuração estão no diretório /etc/. Nesse artigo quero mostrar os principais arquivos de configuração de rede no Ubuntu 12.04. Basicamente, vou escrever sobre os seguinte arquivos:

  • /etc/hostname
  • /etc/hosts
  • /etc/resolv.conf
  • /etc/nsswitch.conf
  • /etc/network/interfaces

/etc/hostname

Esse arquivo contém o nome do sistema. A sintaxe desse arquivo é extremamente simples, veja:

 
cat /etc/hostname
paulo-pc
 

/etc/hosts

Esse arquivo serve para realizar um mapeamento entre endereços IP e nomes de máquinas. Esse arquivo é geralmente usado para identificar máquinas de uma rede local. Nesse arquivo cada linha representa um mapeamento... Seguindo a regra: IP Nome

 
cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 paulo-pc
#Sistema de registro de atividades
10.11.0.250 sistema

/etc/resolv.conf

Esse arquivo também é utilizado para a resolução de nomes em endereços IP. Porém, nesse arquivo não são realizados mapeamentos manuais. No conteúdo desse arquivo são colocados endereços de servidores de resolução de nomes( DNS ).

 
cat /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4

Observação 1: Os IPs 8.8.8.8 e 8.8.4.4 são os servidores de resolução de nomes do Google.


/etc/nsswitch.conf

Esse arquivo determina a ordem das pesquisas que serão feitas para resolução de nomes. Por exemplo, no arquivo a seguir será consultado o arquivo /etc/hosts (files) e depois os servidores que estiverem especificados no arquivo /etc/resolv.conf(DNS)

cat /etc/nsswitch.conf
hosts:          files dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

/etc/network/interfaces

Nesse arquivo são configuradas as interfaces de rede do sistema. A sintaxe básica desse arquivo é a seguinte:

cat /etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 10.11.0.20
netmask 255.255.255.0
gateway 10.11.0.1

Nesse exemplo temos a configuração para interface de loopback ( sabe quando você acessa localhost no firefox? essa interface é que permite isso) e para interface eth0.

A interface eth0 está configurada com IP fixo, ou seja, a interface eth0 sempre irá utilizar o IP 10.11.0.20, máscara de rede 255.255.255.0 (/24) e gateway 10.11.0.1.

Para configurar a interface eth0 para pegar IP através do serviço de DHCP da rede, utilize a seguinte configuração:

cat /etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

Observação 1: a interface eth0 é a primeira placa de rede cabeada... Se você tiver duas placas de redes, provavelmente você terá a interface eth0 e eth1.

Observação 2: Se a sua placa de rede for wireless, provavelmente você terá a interface wlan0.

Pessoal, em um próximo artigo vou escrever sobre os principais comandos utilizados no Ubuntu para configurar as interfaces de redes. Por agora é isso...

Leia mais

Personalizando o BASH

16 de fev de 2015 - Por Paulo Dias

O BASH é uma interface de interação(shell) e também uma linguagem de programação. Existem outras alternativas de shell, mas no GNU/Linux o BASH é o mais utilizado.

Por ser uma linguagem de programação, obiviamente, o BASH possui suporte a variáveis. Essas variáveis podem ser do tipo local ou global.

As variáveis locais são válidas apenas no shell onde foram criadas, não é possível que um 'processo filho' utilize as variáveis locais de um 'processo pai'. A sintaxe para definir uma variável local é:

 
nomeVariavel='valor'
 

Para acessar o valor de uma variável é necessário utilizar o sinal '$', veja um exemplo:

 
nomeVariavel='valor'

echo $nomeVariavel 

# imprime valor

É importante salientar, que diferente de outras linguagens, não deve haver espaços entre o nome da variável, o sinal de igual(=) e o valor da variável.

Para tonar uma variável local acessível para 'processos filhos' é utilizado o comando 'export', assim:

 
export nomeVariavel='valor'
 

As variáveis globais são aquelas acessíveis por todos os porcessos, geralmente essas variáveis contém valores com informações e configurações do BASH. Por exemplo:

  • $PS1 Define a string do prompt do BASH
  • $PATH Define o caminho utilizado para encontrar os programas
  • $HOME Define o diretório home do usuário

O comando 'env' lista as variáveis globais e o comando 'set' lista todas as variáveis.

Para automatizar a configuração de variáveis é possível utilizar alguns arquivos especiais. São eles:

  • /etc/profile
  • /etc/bashrc
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile
  • ~/.bashrc
  • ~/.bash_logout

O arquivo '/etc/profile' é executado durante o processo de autenticação. O arquivo '/etc/bashrc' é executado quando o BASH é inicializado.

Por exemplo, quando é realizado o login através do terminal com 'ctrl + alt + F2', o arquivo '/etc/profile' e o arquivo '/etc/bashrc' serão executados porquê ocorreu o login e o bash foi inicializado. Quando é aberto um shell através da interface gráfica( xterm ), apenas o arquivo '/etc/bashrc' será executado porquê o BASH foi inicializado, mas não houve login.

Os arquivos '/etc/profile' e '/etc/bashrc' são executados para todos os usuários, ou seja, a configuração realizada neles ocorre em todos os usuários do sistema. Em alguns casos é necessário realizar configurações especifcas por usuário, para isso existem os arquivos '~/.bash_profile', '~/.bash_login', '~/.profile', '~/.bashrc' e '~/.bash_logout'.

Esses arquivos ficam na pasta home de cada usuário. Na maioria das vezes apenas alguns desses arquivos são necessários e realmente estão na pasta home do usuário. Porém, é acerto afirmar que algum deles estará na pasta home de cada usuário do sistema.

Esses arquivos são executados assim:

Depois do '/etc/profile': Primeiramente é procurado o arquivo '~/.bash_profile', se esse não existir, é procurado o '~/.bash_login', se esse também não existir, é procurado '~/.bash_login'. Perceba que apenas um desses arquivos será executado... Quando um desses arquivos é encontrado, ele é executado e o BASH para de procurar.

Depois do '/etc/bashrc': '~/.bashrc'

Antes do logout: '~/.bash_logout'

Esse artigo termina aqui, mas vale lembrar que no Ubuntu existem algumas diferenças... No Ubuntu existe o arquivo '/etc/bash.bashrc' e o arquivo '/etc/environment'. Fica como 'lição de casa' pesquisar o que cada um deles faz :)

Leia mais

Agendar tarefas no GNU/Linux

8 de fev de 2015 - Por Paulo Dias

Nesse artigo quero mostrar como agendar tarefas no GNU/Linux... Para realizar os exemplos estou utilizando o Ubuntu 12.04.

No GNU/Linux existem duas alternativas para criar agendamentos de tarefas. O at, que é indicado quando a tarefa agendada deve ser executada uma única vez e o cron, que é utilizado quando a tarefa deve ser executada regularmente (de tempos em tempos).

At

A sintaxe para utilizar o comando at é a seguinte: at horário caminho_completo_comando

Na posição do horário é possível utilizar vários tipos de formatos. No arquivo /usr/share/doc/at/timespec existe uma lista com todos os formatos.

Veja um exemplo de como agendar uma tarefa no at para hoje às 20 horas:

 
at 8pm
 

Nesse momento será aberto um novo shell onde o comando deve ser digitado. No meu Ubuntu esse shell possui a seguinte aparência:

 
at 8pm 
warning: commands will be executed using /bin/sh
at>
 

Após terminar de digitar o comando, utilize o atalho ctrl + d para salvar o agendamento. Esse atalho indica o final de arquivo( EOF ), ou seja, o at entende que o comando foi digitado e deve ser salvo(agendado).

Com isso, o comando foi agendado... Para visualizar a lista de comandos agendados com o at é usado o comando atq ou at -l. Veja um exemplo da saída desse comando:

atq
9 Mon Feb  8 20:00:00 2015 a paulo

Apesar de listar as tarefas agendadas com o horário de execução, através desse comando não é possível verificar quais os comandos serão executados em cada tarefa. Para tanto, é possível visualizar os detalhes de cada tarefa com o seguinte comando:

at -c 9

Onde o número 9 é o id da tarefa. O id é o primeiro número que aparece para cada tarefa listada pelo atq.

Já para remover um comando previamente agendado, é utilizado o comando atrm. A sintaxe desse comando é a seguinte: atrm id

Veja um exemplo onde a tarefa agendada para às 20 horas é removida:

atrm 9

Para definir quais usuários podem ou não executar tarefas no at existem 2 arquivos de controle, são eles: /etc/at.allow e /etc/at.deny

Se o arquivo /etc/at.allow não existir, o arquivo /etc/at.deny será verificado... Se nenhum dos 2 arquivos existirem, apenas o usuário root poderá criar tarefas agendadas.

Cron

Para agendar tarefas no cron é utilizado o comando: crontab -e

O comando crontab -e abre um arquivo (tabela) onde deve ser digitado o comando que vai ser agendado. Essa tabela possui a seguinte aparência no meu sistema:

...
# m h  dom mon dow   command

Nessa tabela temos 6 campos, da direita para esquerda são: Minuto, hora, dia do mês, mês, dia da semana e comando.

Veja um exemplo de como agendar uma tarefa que vai ser executada todos os dias às 20 horas:

# m h  dom mon dow   command

0 20 * * * echo 'paulo' > /dev/pts/0

Nessa tabela é possível utilizar alguns caracteres especiais, por exemplo, o * indica que para essa coluna o comando deve ser executado em todos os casos... Além desse, é possível utilizar os seguintes caracteres:

  • ( , ) Para indicar mais de um valor, por exemplo, no mês 5 e 6 é igual a 5,6
  • ( - ) Para indicar um intervalo, por exemplo, do dia 10 até o dia 20 é igual a 10-20
  • ( / ) Para indicar um passo(incremento), por exemplo, executar a cada 5 minutos é igual a */5

Veja um exemplo onde uma tarefa é agendada para executar nos dias 3, 6, 7 e 8, iniciando às 20h e que seja repetida a cada 2 minutos até às 21h:

# m h  dom mon dow   command

*/2 20 3,6-8 * * echo 'paulo' > /dev/pts/0

Da mesma forma que acontece com o at, existem 2 arquivos para controlar quem pode agendar tarefas no cron, são eles: /etc/cron.allow e /etc/cron.deny. Porém, se nenhum dos 2 existir, diferente do que acontece com o at, todos os usuários poderão agendar tarefas no cron.

Além de escrever comandos diretamente na tabela cron, também é possível agendar tarefas usando as seguintes pastas: /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly.

Para agendar uma tarefa, basta criar um shell script e move-lo para a pasta correspondente... O script será executado conforme a pasta. De hora em hora(cron.hourly). Diariamente(cron.daily). Semanalmente(cron.weekly). Mensalmente(cron.monthly)

Bom pessoal, obviamente, esse artigo não mostra todas as possibilidades desses comandos, mas vou encerrar por aqui... Quem tiver interesse em saber mais pode verificar os links a seguir e ler o manual de cada comando através do comando man, veja um exemplo: man at

http://www.dltec.com.br/blog/linux/agendando-tarefas-com-o-comando-at-no-linux/ http://www.vivaolinux.com.br/artigo/Usando-cron-e-crontab-para-agendar-tarefas
Leia mais

Administração de usuários no Ubuntu 12.04

8 de nov de 2014 - Por Paulo Dias

Nesse artigo vou escrever sobre a administração de usuários no GNU/Linux. Estou usando o Ubuntu 12.04 para realizar os testes, mas tudo deve ocorrer normalmente em outras distribuições.

No GNU/Linux existem 4 arquivos que são usados para administrar usuários, são eles:

  • /etc/passwd
  • /etc/shadow
  • /etc/group
  • /etc/gshadow

Observaçãp: Você pode consultar o manual desses arquivos com o seguinte comando: man 5 nome_arquivo.

O arquivo /etc/passwd é responsável por armazenar informações da conta de cada usuário. Ele segue a seguinte estrutura:

 usuario : x : id_usuario : id_grupo_primario : infos( gecos ) : caminho_home : caminho_shell

Para ver o conteúdo desse arquivo execute o seguinte comando no terminal:

 getent /etc/passwd

O arquivo /etc/shadow armazena as senhas dos usuários ( na verdade um hash delas ) e infomações relacionadas ao tempo de validade das senhas.

Antigamente o arquivo passwd guardava a senha do usuário, mas por segurança essa informação foi migrada para o shadow. Assim, a senha no arquivo passwd foi substituida por um x, indicando dessa forma que o sistema faz uso do arquivo shadow.

Para visualizar o conteúdo do arquivo /etc/shadow você também pode usar o comando getent, mas é necessário utilizar o usuário root( sudo ) ou um usuário que esteja no grupo shadow.

O arquivo /etc/group armazena informações sobre os grupos do sistema. Ele segue a seguinte estrutura:

 grupo : x : id_grupo : usuarios_dentro_do_grupo

Da mesma forma que os arquivos anteriores, é possível usar o comando getent para visualizar o conteúdo desse arquivo.

O arquivo /etc/gshadow é responsável por armazenar as senhas dos grupos.

Conhecendo as estruturas desses arquivos e tendo as permissões necessárias é possível fazer qualquer tipo de admnistração de usuários no GNU/Linux. Porém, não é recomendado alterar esses arquivos manualmente, o ideal é utilizar os seguintes comandos:

  • chage
  • passwd
  • usermod
  • groupmod
  • useradd
  • userdel
  • groupadd
  • groupdel

O comando chage serve para alterar caracteristicas da senha do usuário.

Veja a saida do comando 'chage -l paulo' no meu sistema:


Última mudança de senha     : Out 28, 2014
Senha expira     : nunca
Senha inativa     : nunca
Conta expira      : nunca
Número mínimo de dias entre troca de senhas  : 0
Número máximo de dias entre troca de senhas  : 99999
Número de dias de avisos antes da expiração da senha : 7

Essas informações também podem ser alteradas com o comando chage, por exemplo, com o comando a baixo altera a data de expiração da conta:

sudo chage -E 11/09/2020 paulo # a data está no padrão mm/dd/aaaa

Para saber mais utilize o comando man chage.

No GNU/Linux além de um arquivo passwd, também existe um comando com esse mesmo nome. O comando passwd serve para alterar a senha de um usuário. ( evidente que é necessário permissões de administrador para trocar a senha de outro usuário ). O seguinte comando altera a senha do usuário 'paulo':

passwd paulo 

Tendo as devidas permissões também é possível bloquear a conta de um usuário com o comando passwd. Veja:

sudo passwd -l paulo #bloqueia 
sudo passwd -u paulo #desbloqueia

Através do comado usermod também é possível alterar várias informações da conta de um usuário. Entre outras, é possível alterar os grupos, o diretório home e o shell do usuário:

sudo usermod -G adm,cdrom,sudo paulo # altera os grupos
sudo usermod -d /home/paulo2 paulo # altera o home
sudo usermod -s /bin/csh paulo # altera o shell

Veja mais com o comando man usermod.

Assim como o usermod serve para fazer alterações nos usuários o comando groupmod faz alterações nos grupos:

groupmod -n novo antigo

Esse comando altera o nome do grupo 'antigo' para 'novo'.

O comando useradd é utilizado para inserir um novo usuário no sistema. Veja:

sudo useradd -m -s /bin/bash paulo

Nesse exemplo o -m é para criar o diretório home e o -s é para especificar o shell do novo usuário. Depois de criar o usuário ainda é necessário utilizar o comando passwd para especificar uma senha, somente depois disso o usuário poderá ser usado.

Para remover um usuário no sistema é utilizado o comando userdel assim:

sudo userdel -r paulo

É importante utilizar o -r para garantir que o diretório home do usuário será removido.

O comando groupadd serve para adicionar um grupo no sistema, veja o exemplo:

sudo groupadd grupo

E para remover um grupo é usado o comando groupdel:

sudo groupdel grupo

Para remover um grupo que seja primário de algum usuário é necessário primeiro excluir o usuário com o comando userdel.

Feito, por hoje é isso! Existem vários outros comandos que são utéis para admnistração de usuários no GNU/Linux, segue mais alguns comandos para quem quiser saber mais: id, finger, chfn, adduser( debian-like ), who, users, fuser ...

T+
Leia mais