como eu uso o git

Faz tempo que não escrevo aqui. Nesse meio tempo estive em 3 países diferentes, e muita aconteceu. Agora chegou a hora de um post simples e rápido sobre como tenho usado o git, que talvez ajude muita gente.

Os projetos de código aberto ficam normalmente hospedados no github. Também mantenho uma cópia na minha máquina do slicehost, que vai pro backup. Já os projetos de código proprietário, mando apenas pra minha máquina do slicehost.

Nessa máquina do slicehost, uso gitosis pra administrar o repositório. Ele é simples, prático, e funciona via ssh, o que é bem conveniente. Melhor ainda, é fácil de instalar e gerenciar, e usa o próprio git pra configurar o repositório. No README já tem toda a explicação sobre como instalar e gerenciar.

Se você está pensando em usar git também, e vem do svn, veja este link. O que posso te adiantar sobre o git, em relação ao svn (ou mesmo cvs, ou pior ainda, clearcase) é o seguinte: sistema de controle de versão offline é absurdamente mais produtivo. Especialmente no caso do git, criar e gerenciar diferentes branches é muito melhor, o merge entre diferentes branches ou até entre diferentes revisões (usando repositório remoto) é muito bom, e mesmo quando falha é bem simples de resolver. Tem todos os recursos que você já está acostumado, e os que precisa: tag, branch, archive.

Ainda é possível manter uma working copy local com git, e usar o repositório svn. Veja este manual. Se precisar usar git com clearcase, tem este e este link.

O manual do usuário (do kernel.org) é bem completo e cheio de exemplos. Também tem o video do Linus falando sobre o git no Tech Talk, no Google.

Anúncios

unix shell

O interpretador de comandos dos sistemas operacionais Unix e Unix-like é a interface tradicional para operar o computador. Por meio de comandos, o usuário direciona o sistema para tarefas específicas.

O interpretador, conhecido como shell, normalmente suporta uma linguagem de script para que os comandos possam ser executados de maneira sequencial, permitindo automatizar tarefas rotineiras.

Mas, internamente, o que faz o shell? Bem, as etapas básicas são as seguintes:

  1. imprime o prompt de comando: $ para usuário ou # para root
  2. lê a linha digitada pelo usuário
  3. remove CRLF (\r\n) e depois separa a linha em strings, onde houver espaço
  4. fork(): duplica o conteúdo do próprio processo (parent) no sistema, criando um processo filho (child)
    • no child: execvp() executa o comando digtado – tipo ls -l
    • no parent: wait(NULL) aguarda o processo filho terminar

Embora os shells mais avançados como bash e csh possuam uma enorme quantidade de funções, tais como as da biblioteca readline, um shell apenas com as etapas mencionadas acima funciona perfeitamente.

Aqui está o exemplo:

/* 20090118 - AF */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

static char *stripcrlf(char *line)
{
    char *p;
    for(p = line; *p; p++)
        if(*p == '\r' || *p == '\n') { *p = '\0'; break; }
    return line;
}

static void split(char *line, char **args)
{
    while(*line) {
        while(*line && *line == ' ') *line++ = '\0';
        *args++ = line;
        while(*line && *line != ' ') line++;
    }
}

int main()
{
    char *p, line[4096], *args[sizeof line/2];

    for(;;) {
        fprintf(stdout, getuid() ? "$ " : "# ");
        fflush(stdout);

        memset(line, 0, sizeof line);
        if(!fgets(line, sizeof line, stdin)) {
            fprintf(stdout, "\n");
            clearerr(stdin);
            continue;
        }

        p = stripcrlf(line);
        if(*p) split(p, args);
        else continue;

        if(!fork()) {
            if(execvp(args[0], args) == -1) perror("exec");
        } else wait(NULL);
    }
    return 0;
}

NOTA: a imagem no topo foi criada por Paul Bourke em 1989, encontrada neste site.


bash e arquivos com espaço no nome

Você já precisou fazer um “for” em arquivos ou diretórios que têm espaço no nome? Como o “for” do bash trata o espaço como delimitador, o seguinte comando não funcionaria:

for zz in $(find . -iname \*.mpg); do echo "nome: $zz"; done

Caso haja um espaço no nome dos arquivos, cada parte dele será tratada como $zz. Nesse caso, é bem simples resolver – usando os próprios recursos do bash.
Abaixo o exemplo:

find . -iname \*.mpg | while read zz; do echo "nome: $zz"; done

Há!


socklist no bsd/mac os?

No linux é bem fácil extrair uma lista de processos e suas respectivas portas alocadas com bind(2), seja tcp ou udp.

No bsd e mac os não tem socklist, pois esse programa é distribuído com o pacote procps, que usa o /proc do linux. Aí, só rola usando lsof.

Por porta (usando ipv4):

lsof -ni 4:porta

Por processo (PID, usando ipv4):

lsof -np PID -a -i 4

criptografando arquivos com senha

Existem diversas maneiras de garantir a segurança da informação no Linux. Há alguns programas que criptografam partições, como dm-crypt. Também, há o crypto loop que criptografa loop devices.

Porém, se você precisa simplesmente criptografar um arquivo para que seja enviado por email, ou transferido via FTP, pode usar o gpg:

$ gpg -c arquivo.tgz
Enter passphrase:
Repeat passphrase:

Após colocar a senha, o arquivo.tgz.gpg será criado. Para decriptar o arquivo, o processo é muito semelhante, veja:

$ gpg arquivo.tgz.gpg
gpg: CAST5 encrypted data
Enter passphrase:

Com a senha correta, o arquivo.tgz será criado com o conteúdo original.


usando find para encontrar arquivos antigos

A maioria dos administradores de sistemas UNIX provavelmente já fez isso. Se não, ainda vai precisar.
É uma coisa simples, que todo mundo sabe que é possível, mas sempre esquece. Eu mesmo esqueço e por isso vou postar aqui, ai fica mais fácil quando esquecer denovo.

find /tmp -iname \*.jpg -atime +1 -print

Esse comando mostra os arquivos com extensão JPG (case insensitive, -iname) no diretório /tmp, que tenham sido acessados a mais de 1 dia – por isso +N. Pode-se usar -N para datas menores que N: se fosse -1, encontraria arquivos que foram acessados a menos de 1 dia. Quando não há sinal, encontra com exatidão: se fosse -atime 2, encontraria arquivos que foram acessados a exatamente 2 dias.

No manual find(1) há a descrição de todas opções, como -atime, -amin e -anewer. Também, das variantes com -ctime e -mtime (-cmin, etc).

Só pra lembrar:

  • Estes dados são armazenados na struct stat, descrita no manual stat(2)
  • o atime é atualizado quando há algum tipo de acesso no arquivo – com execve(2), read(2), etc.
  • o mtime é atualizado quando há modificação no arquivo – quando novos dados são escritos nele, truncate(2), write(2). No caso de diretórios, o mtime do diretório é atualizado quando arquivos são criados ou removidos nele.
  • o ctime é atualizado quando há escrita no arquivo, ou quando suas permissões são alteradas – write(2), chmod(2), chown(2), etc.

abrindo pacotes debian

Um pacote Debian (do Debian, Ubuntu, etc) é um arquivo criado com o GNU ar. Pra falar sobre ele, há uma pequena dificuldade e possível limitação na língua portuguesa – pelo menos pra mim.

O GNU ar é usado para manipular arquivos (archives), que são compostos por uma coleção de arquivos (files), cada um com suas permissões (timestamp, uid, mode, etc). É semelhante ao GNU tape archiver (tar), ou mesmo um arquivo ZIP sem compressão. Uma das particularidades deste formato é que ele é considerado parte do ambiente de desenvolvidomento, pois os arquivos deste tipo são usados também como bibliotecas estáticas no sistema – aquelas bibliotecas com extensão .a, que contém diversos objetos .o dentro.

Veja:

$ file /usr/lib/libgdict-1.0.a
/usr/lib/libgdict-1.0.a: current ar archive

$ ar vt /usr/lib/libgdict-1.0.a
rw-r--r-- 0/0    632 Sep 18 13:19 2007 libgdict_1_0_la-gdict-debug.o
rw-r--r-- 0/0  21328 Sep 18 13:19 2007 libgdict_1_0_la-gdict-context.o
rw-r--r-- 0/0  43240 Sep 18 13:19 2007 libgdict_1_0_la-gdict-client-context.o
rw-r--r-- 0/0  27736 Sep 18 13:19 2007 libgdict_1_0_la-gdict-database-chooser.o
rw-r--r-- 0/0  67416 Sep 18 13:19 2007 libgdict_1_0_la-gdict-defbox.o
rw-r--r-- 0/0  15256 Sep 18 13:19 2007 libgdict_1_0_la-gdict-entry.o
rw-r--r-- 0/0   9992 Sep 18 13:19 2007 libgdict_1_0_la-gdict-enum-types.o
rw-r--r-- 0/0   2064 Sep 18 13:19 2007 libgdict_1_0_la-gdict-marshal.o
rw-r--r-- 0/0  27720 Sep 18 13:19 2007 libgdict_1_0_la-gdict-source.o
rw-r--r-- 0/0  14904 Sep 18 13:19 2007 libgdict_1_0_la-gdict-source-loader.o
rw-r--r-- 0/0  23992 Sep 18 13:19 2007 libgdict_1_0_la-gdict-speller.o
rw-r--r-- 0/0  27608 Sep 18 13:19 2007 libgdict_1_0_la-gdict-strategy-chooser.o
rw-r--r-- 0/0   4600 Sep 18 13:19 2007 libgdict_1_0_la-gdict-utils.o

Os pacotes Debian não são muito diferentes. Embora devam ser manipulados com as próprias ferramentas do Debian – tais como dpkg – nada impede de abrí-los e verificar seu conteúdo, usando o GNU ar.

Com o comando dpkg-deb -I arquivo.deb você obtém a descrição do pacote. Usando dpkg-deb -c arquivo.deb você obtém a lista de arquivos que este pacote irá instalar, quando usar o comando dpkg -i arquivo.deb. O conteúdo do pacote Debian é o seguinte:

$ file sox_13.0.0-1build1_amd64.deb
sox_13.0.0-1build1_amd64.deb: Debian binary package (format 2.0)

$ ar vt sox_13.0.0-1build1_amd64.deb
rw-r--r-- 0/0      4 Jul  3 00:55 2007 debian-binary
rw-r--r-- 0/0   1263 Jul  3 00:55 2007 control.tar.gz
rw-r--r-- 0/0 220555 Jul  3 00:55 2007 data.tar.gz

O arquivo chamado debian-binary contém a versão do pacote – uma linha escrito “2.0”. O arquivo control.tar.gz contém os arquivos de controle do pacote, como descrição, dependências, scripts para executar antes e/ou depois de instalar o pacote, scripts pro contrab, etc. Por fim, o arquivo data.tar.gz contém os arquivos que este pacote irá instalar no sistema.

Para extrair o conteúdo pode-se usar o comando ar vx nome.deb.