Voltando a falar no git
- publicado em 02 de janeiro de 2012
Boas pessoal, essa aqui é bem rápida:
Acabei de reler um post que escrevi a um tempo atrás. O post fala como usar o git com http. O negócio é zuado. Funciona, mas não é o jeito certo de fazer a coisa.
O melhor é usar o gitorious, e você ainda pode baixar o código e ter a sua própria instalação.
Simples assim.
Poo no Perl!
- publicado em 28 de dezembro de 2011
Boas pessoal. Tô de volta. :) Depois de um bom tempo sem postar nada, vou aproveitar minha semaninha de folga pra tirar as teias do porão e vamos falar um pouquinho sobre orientação a objetos no Perl.
Mas o Perl é um cara sem classe, não?
No Perl realmente não existe uma palavra mágica class ou algo do tipo, mas a gente pode criar classes sim!
As classes no Perl são criadas o mecanismo de package que também é usado mais usualmente para criar módulos tradicionais. E os objetos… bom, os objetos são referências abençoadas ! :P
Referência abençoada? Que diabo é isso?
Calma… nada de misticismos. Uma referência abençoada é só uma referência que foi passada como argumento para a função bless. É essa função a responsável por dizer: “essa referência pertence a este package (classe)”. Depois de abençoada, você será capaz de chamar funções através dessa referência, ou, em outras palavras, você terá métodos!
Entendi, mas já cansei de papo…
Beleza, já falei bastente, e agora é hora do código.
Pra este exemplo vou criar uma classe (package) Pessoa (como um módulo normal do Perl, isso será gravado em um arquivo chamado Pessoa.pm), e nessa classe criarei o contrutor da classe e os seus outros métodos. Agora sim, o código:
package Pessoa; # Arquivo Pessoa.pm
use strict;
use warnings;
# Aqui é o contrutor da classe.
# O nome 'new' não é uma obrigação, só
# uma convenção de uso.
sub new{
# classe onde o a referência será abençoada.
# Isso aqui não precisa ser passado como parâmetro
# na hora de instanciar o objeto, é passado implicitamente
my $class = shift;
# Nossa referência que será abençoada.
# Pode ser uma referência qualquer, não necessáriamente
# uma referência a um hash;
my $self = {};
$self->{NOME} = undef;
$self->{IDADE} = undef;
# Agora a mágica acontece
bless($self, $class);
return $self;
}
# Métodos pra proteger o acesso aos nossos atributos
sub nome{
# Como $class no contrutor, $self aqui também é parâmetro implícito
my $self = shift;
$self->{NOME} = shift if @_;
return $self->{NOME};
}
sub idade{
my $self = shift;
$self->{IDADE} = shift if @_;
return $self->{IDADE};
}
# Outro metodozinho só de exemplo
sub fale{
my $self = shift;
my $fala = shift || "Qualquer coisa";
return $fala
}
# Precisa retornar um valor verdadeiro
1;
Agora, vamos criar uma subclasse de Pessoa
package PessoaMuda; # Arquivo PessoaMuda.pm
# Importando a super classe
use Pessoa;
# Aqui estamos dizendo que PessoaMuda é uma Pessoa
@ISA = (Pessoa);
# Sobrescrevendo o método fale pra que retorne nada...
sub fale{
my $self = shift;
return
}
1;
E, por fim, vamos usar nossos objetos
#!/usr/bin/env perl
use strict;
use warnings;
# Importando nossas classes
use Pessoa;
use PessoaMuda;
# Nova instância de Pessoa;
my $p = Pessoa->new();
$p->nome('Alguém');
print $p->nome();
$p->idade(10000);
print $p->idade();
print $p->fale('Eu nasci a 10000 anos atrás...') . "\n";
# Uma pessoa muda
my $pm = PessoaMuda->new();
$pm->nome('Ninguém');
print $pm->nome();
$pm->idade(10000);
print $pm->idade();
# Mudos não falam, lembra? Sobrescrevemos o método...
print $pm->fale('Alguma coisa');
Bom, é isso! Pra mais sobre orientação a objetos no Perl, leiam o perltoot.
Valeu, e até a próxima!
Dissecando um inseto (ou como usar o pdb, the Python Debugger)
- publicado em 16 de agosto de 2010
Boas, pessoal! Hoje eu estou aqui pra mostrar como se usa o (básico do) Python Debugger, o pdb, que é (óbvio) um depurador pra se usar com o Python. Este exemplo é feito usando o Python 3.
Mas… como é?
Bom, existe mais de uma maneira de usar o pdb. A que vou mostrar é chamando o pdb como um script para depurar outro script. Então, primeiro, vamos criar um scriptosco com um erro mais tosco ainda pra gente começar a brincar com o pdb. O scriptosco é o seguinte:
#-*- coding: utf-8 -*-
def divide(a, b):
erro = False
try:
return float(a) / float(b)
except:
erro = True
if erro:
raise Exception("Não vou te dizer qual é o erro...")
a = 1
b = 2
divide(a, b)
a = 3
b = 0
divide(a, b)
Bom, rodando isso aí, a gente tem o seguinte:
$ $python3 exemplopdb.py
Traceback (most recent call last):
File "exemplopdb.py", line 18, in
divide(a, b)
File "exemplopdb.py", line 11, in divide
raise Exception("Não vou te dizer qual é o erro...")
Exception: Não vou te dizer qual é o erro...
Será que esse tal de pdb funciona mesmo?
Agora que temos um erro, podemos usar o pdb pra achar cara. A gente vai fingir que não vê nada errado até a hora certa, tá? :P A sintexe pra se chamar o pdb é a seguinte: python -m pdb <meu_script> Então, ao chamar nosso doente junto com o pdb, a gente vai cair no shell do pdb. Assim:
$ python3 -m pdb exemplopdb.py
--Return--
> /media/5511fc83-ad85-484b-9b0e-0948abcb6026_/virtualpython/lib/python3.1/encodings/__init__.py(67)normalize_encoding()->'utf_32_be'
-> return ''.join(chars)
(Pdb)
Nós começaremos criando breakpoints nas linhas 11 e 18. Fazemos isto com o comando b[reak]. Depois, utilizando o comando c[ontinue], continuaremos a execução do programa até que algum breakpoint seja encontrado. E por fim, usaremos o comando list para listar um trecho de código e ver onde paramos.
(Pdb) break exemplopdb.py:11
Breakpoint 1 at /media/sda6/Projetos & afins/scripts/exemplopdb.py:11
(Pdb) b exemplopdb.py:18
Breakpoint 2 at /media/sda6/Projetos & afins/scripts/exemplopdb.py:18
(Pdb) c
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(18)()
-> divide(a, b)
(Pdb) list
13 a = 1
14 b = 2
15 divide(a, b)
16 a = 3
17 b = 0
18 B-> divide(a, b)
19
[EOF]
(Pdb)
Nosso primeiro breakpoint é bem na chamada da função, então vamos «entrar na função» e acompanhar a execução. A gente faz isso com o comando s[tep]. Uma vez na função, a gente pode acompanhar a execução linha-por-linha usando o comando n[ext] e também pode imprimir os valores das variáveis com print.
(Pdb) s
--Call--
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(3)divide()
-> def divide(a, b):
(Pdb) list
1 #-*- coding: utf-8 -*-
2
3 -> def divide(a, b):
4 erro = False
5 try:
6 return float(a) / float(b)
7 except:
8 erro = True
9
10 if erro:
11 B raise Exception("Não vou te dizer qual é o erro...")
(Pdb) n
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(4)divide()
-> erro = False
(Pdb) n
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(5)divide()
-> try:
(Pdb) n
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(6)divide()
-> return float(a) / float(b)
(Pdb) print(a, b)
(3, 0)
(Pdb) n
ZeroDivisionError: 'float division'
> /media/sda6/Projetos & afins/scripts/exemplopdb.py(6)divide()
-> return float(a) / float(b)
(Pdb)
Bom, aí matamos o erro, não? Funciona mesmo! Moral da história: As vezes o pdb pode salvar várias horas do seu dia. Faça dele um amigo. :)
Liberando espaço no HD com localepurge
- publicado em 07 de julho de 2010
Bom, faz tempo que eu não venho aqui, então aqui vai uma rapidinha só pra tirar as teias-de-aranha. Esse programinha aí, o localepurge, é um cara que apaga as traduções de programas e manuais que estão nos idiomas que você não usa. Dependendo do tanto de coisa que você tem instalado, vai ter bastante espaço liberado. Isso me libera pra mais de 500 MiB. Pra instalar no Debian, como sempre, é simples.
# aptitude install localepurge
E depois:
# localepurge
É isso.
Corrigir erro “Network Unreachable” com Java no Debian
- publicado em 04 de março de 2010
Puta, perdi uma tarde inteira quebrando a cabeça com isso. Estava tentando usar o Squirrel-SQL (e o Sql Developer também), mas sempre dava merda, com o java dizendo que «Network Unreachble». Depois de bastante tempo, esse cara me deu a resposta. O que acontece é que no arquivo /etc/sysctl.d/bindv6only.conf a variável net.ipv6.bindv6only estava marcada como 1, e essa é a fonte do problema. Esta variável tem que estar marcada como 0. Pra arrumar isso, use:
# sed -i 's/net.ipv6.bindv6only\ =\ 1/net.ipv6.bindv6only\ =\ 0/' /etc/sysctl.d/bindv6only.conf
# invoke-rc.d procps restart
É isso aí.
Uma pincelada no GIT parte II - Configurando HTTP
- publicado em 08 de janeiro de 2010
NÃO LEIA ISSO - ou melhor, pode até ler, mas esse aqui não é o jeito certo de fazer as coisas. :P Leia esse aqui
Antes de mais nada, a fonte primária de informação é essa aqui. Isto aqui é a continuação do post anterior sobre o git. Como prometido, hoje vou explicar como configurar o git para usar http ou invés de ssh.
Começando do começo
Bom, começarmos a configurar o servidor você vai precisar de algumas coisas instaladas nele. São elas:
Um servidor web apache
Git
Você vai precisar também ter acesso como root neste servidor para poder fazer a configuração inicial do repositório. Antes de prosseguir, vale uma ressalva: O apache é um treco chato… Se você pegar os fontes e compilar, o “document root” e os arquivos de configuração serão em um lugar. Se você estiver usando um Red Hat serão em outro, em um Debian serão em outro ainda. E no windows então! Nem faço idéia como funciona o apache no windows.
Por isso, primeiro sempre darei uma explicação «genérica» de como a coisa funciona. Nos exemplos que darei, os caminhos de arquivos e tudo mais serão baseados em Debian. Se você uma um sistema operacional diferente, leia o manual do apache e veja onde estão localizados seus arquivos.
Configurando o servidor
A primeira coisa a fazer é certificar-se que o módulo dav_module está sendo carregado pelo apache. Isto pode ser feito adicionando as seguitnes linhas os seu httpd.conf:
LoadModule dav_module libexec/httpd/libdav.so
AddModule mod_dav.c
DAVLockDB "/usr/local/apache2/temp/DAV.lock"
No Debian, isto pode ser feito de uma outra maneira. Deste jeito:
# a2enmod dav_fs
# a2enmod dav
Depois disto, é preciso criar um repositório «pelado» para o git. Para isto, criaremos um diretório dentro do nosso «document root», criaremos o reporitório dentro deste diretório recém criado, e por fim, deixaremos o usuário do apache como dono deste diretório e de todos os seus sub-diretórios. No Debian fica assim:
# mkdir /var/www/novo_projeto.git
# cd /var/www/novo_projeto.git
# git --bare init
# cd ../
# chown -R www-data:www-data novo_projeto.git/
Agora, vamos criar um usuário/senha para acessar o projeto . A sintaxe é assim: htpasswd -c /caminho/para/o/arquivo/de/senha <usuario>.
O diretório onde se encontra o arquivo de senhas tem que ser lido pelo apache e, de preferência, não ser lido pelo resto do mundo. O parâmetro -c passado ao htpasswd significa que criaremos um novo arquivo. Se o arquivo já exitir e você quiser apenas acrescentar mais um usuário, htpasswd deve ser chamado sem o parâmetro -c. Aqui no Debian, ficou assim:
# htpasswd -c /etc/apache2/passwd.git gituser
Depois de criado o usuário, vamos definir as regras do apache para o diretório do nosso repositório. Geralmente você precisaria adicionar algo assim ao seu httpd.conf:
<Location /meu_repo>
DAV on AuthType Basic
AuthName "Git"
AuthUserFile /caminho/para/o/arquivo/de/senha
Require valid-user
</Location>
Como o Debian lê automaticamente os arquivos em /etc/apache2/conf.d/, eu criei o arquivo /etc/apache2/conf.d/git.conf e adicionei o seguite a ele:
<Location /novo_projeto.git>
DAV on AuthType Basic
AuthName "Git"
AuthUserFile /etc/apache2/passwd.git
Require valid-user
</Location>
Agora, reinicie o apache. No Debian fica assim: # /etc/init.d/apache2 restart Neste ponto o servidor já deve estar funcionando corretamente. Para testar, acesse o seu servidor da seguinte maneira: http://servidor/novo_projeto.git
O servidor peguntará seu usuário/senha. Depois de informá-las, se você ver uma listagem de diretórios e arquivos do git, o servidor está funcionando corretamente.
Configurando o cliente
Agora que o servidor já está configurado, é hora de configurar o cliente. A primeira coisa a fazer, é informar nosso usuário e senha pra que não tenhamos que ficar digitando isso toda vez… é chato! Fazemos isso adicionando as seguintes linhas ao arquivo $HOME/.netrc:
machine <servidor> login <usuário> password <senha>
Como nossa senha está aí, é bom restringir o acesso a este arquivo. Fazemos isto assim:
$ chmod 600 ~/.netrc
Depois disso, precisamos configurar o git para acessar nosso servidor. Isso é muito simples.
$ git config remote.novo_projeto.url http://<usuário>@<servidor>/novo_projeto.git/
OBS: Não esqueça da “/” no final da url, senão você vai cair num redirecionamento eterno…
Bom, aqui já está tudo configurado. Só o que precisamos fazer agora é “empurrar” os arquivos do projeto para o servidor.
$ git push novo_projeto master
Fetching remote heads...
refs/ refs/heads/ refs/tags/
updating 'refs/heads/master' from 5b0bc00758855aef6dafe7aa9849443aea0dbf1c to b4857d97182a582c76961370de489b14385f9af9
sending 13 objects done
Bom, é isso aí! Git configurado pra usar HTTP. Agora você que decide como usar seu Git.
Uma pincelada no GIT
- publicado em 05 de janeiro de 2010
O git é um programa para controle de versões. O que mais me agrada nele é a sua flexibilidade e a sua simplicidade de uso. O que segue aí é só uma amostra do que o git pode fazer por você. Para mais informações visite http://git-scm.com/
Apresentando-se ao git
O que faremos aqui é versionar um projeto que já temos. Neste exemplo meu projeto estará em /home/juca/src/novo_projeto. Então, vamos lá! Depois de instalado o git (instruções de instalação aqui) a primeira coisa a fazer, é apresentar-se ao git. Para tanto, vamos informar ao git nosso nome e email.
$ git-config --global user.name "Juca"
$ git-config --global user.email "juca@minhacasa.nada"
Versionando nosso primeiro projeto
Agora que já nos apresentamos ao git, vamos versionar nosso projeto. A primeira coisa é ir até o diretório onde está seu projeto, depois dar um «git init» neste diretório para criar um novo repositório do git, e por fim, adicionar e “commitar” os arquivos do projeto. A coisa fica assim:
$ cd /home/juca/src/novo_projeto
$ git init Initialized empty Git repository in /home/juca/src/novo_projeto/.git/
$ git add .
$ git commit
Com o que fizemos até agora, já temos o projeto versionado. Para ver o log dos commits use «git log», assim:
$ git log
commit dc00b38b6beb9db50d8b0ad0fb7e6a80689c80cb
Author: Juca
Date: Tue Jan 5 12:41:51 2010 -0200
Primeiro commit do tutorial
Podemos também listar os arquivos que estão sob o controle de versão usando «git ls-files», assim:
$ git ls-files arquivo1 arquivo2
Alterando e trabalhando com os arquivos do projeto
Agora, vamos alterar um arquivo pra ver como fica.
$ emacs arquivo1
Altere o que quiser e salve o arquivo. Antes de adicionar e commitar podemos ver o que foi alterado com «git diff»:
$ git diff --color arquivo1
diff --git a/arquivo1 b/arquivo1
index a353720..d80b33a 100644
--- a/arquivo1 +++ b/arquivo1
@@ -1 +1,2 @@ -Oi, eu sou o arquivo1. Essa merda é só pra brincar com o git e escrever o tuto... \ No newline at end of file +Oi, eu sou o arquivo1 (agora alterado). +Essa merda é só pra brincar com o git e escrever o tuto... \ No newline at end of file arquivo1
Obs: A opção «–color» é usada para que o resuldado do diff fique colorido, mas aqui no tuto as cores foram pro saco… Agora, é só adicionar e commitar o arquivo modificado. $ git add arquivo1 $ git commit
Criando branches
Agora vamos falar de branches. Branches não custam nada no git, e são muito fáceis de manejar. Todo novo repositório do git é criado com um branch chamado «master». Tudo o que fizemos até agora foi neste branch. Vamos criar um novo agora com «git branch»
$ git branch # primeiro para ver os branchs que já existem
* master
$ git branch teste #criando o branch 'teste'
$ git checkout teste #mudando para o branch 'teste'
Agora, vamos alterar um arquivo no branch teste.
$ emacs arquivo1
Altere e salve o arquivo. Em seguida, adicione e commite o arquivo modificado
$ git add arquivo1
$ git commit
Neste ponto, temos arquivos que têm diferenças entre a versão do branch master e do branch teste. Para «juntar» as versões dos dois branches usaremos «git merge». O que faremos é o seguinte: Primeiro voltaremos ao branch master e depois faremos o merge das versões. git checkout master git merge teste Agora, depois do merge, você pode ver que as alterações feitas no branch teste também estão visíveis no branch master. Sendo assim, podemos apagar o branch teste
$ git branch -D teste
Trabalhando com os outros
Bom, até agora foi o basicão do «eu trabalhando comigo mesmo», mas a graça da coisa é distribuir o código e desenvolver com os outros, não? Então! agora vamos ver como usar o git para distribuir (ou receber de outros) o código.
Clonando um projeto
Vamos supor que eu (Juca) estou em hostjuca e um outro cara (Zé) está em hostze e quer contribuir com o projeto. Para fazer isto, o git pode usar ssh ou http. Vamos começar pelo ssh é qué mais simples. O Zé precisa ter acesso liberado no ssh da minha máquina. hostjuca será o repositório «principal» O Zé ainda não tem uma cópia do projeto, então a primeira coisa a fazer é clonar o projeto com «git clone». A sintaxe do «git clone» é assim (lembrando que estamos usando ssh):
git clone ssh://[usuario@]host:[porta]/caminho/pro/repositorio
Então, pro Zé clonar meu projeto, a coisa ficaria assim:
ze@hostze:~/src$ git clone ssh://ze@hostjuca:22/home/juca/src/novo_projeto
Initialized empty Git repository in /home/ze/src/novo_projeto/.git/
ze@hostjuca\'s password:
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 7 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (7/7), done.
Agora o Zé já tem os arquivos do meu projeto e pode brincar a vontade.
ze@hostze:~/src$ cd novo_projeto
ze@hostze:~/src/novo_projeto$ vi arquivo2 #O Zé é filho do capeta, vocês viram, né?
ze@hostze:~/src/novo_projeto$ git add arquivo2
ze@hostze:~/src/novo_projeto$ git commit
Sincronizando os repositórios
Agora as versões do Juca e do Zé estão diferentes. Temos duas opções para sincronizar estas duas versões. Ou o Juca “puxa” as mundaças do Zé ou o Zé empurra as mudanças dele para o repositório do Juca. Antes de prosseguirmos, vale uma explicaçãozinha sobre o comportamento do git. O git não gosta que você empurre o mesmo branch que você clonou (ou puxou). Parece estranho, mas tem sentido. Tente empurrar o branch master que você verá um aviso muito explicativo.
Empurrando as coisas
Como o Zé já tem acesso a máquina do Juca, vamos deixá-lo empurrar as mudanças para o repositório principal. Isso será feito com «git push». A sintaxe do «git push» é a seguinte:
git push ssh://[usuario@]host:[porta]/caminho/pro/repo branch_local
Por causa do comportamento do git, o Zé tem que primeiro criar um novo branch e empurrar este novo branch. A coisa fica assim:
ze@hostze:~/src/novo_projeto$ git branch branchdoze
ze@hostze:~/src/novo_projeto$ git push ssh://ze@hostjuca:22/home/juca/src/novo_projeto branchdoze
ze@hostjuca\'s password:
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 349 bytes, done.
Total 3 (delta 0), reused 0 (delta 0) To ssh://ze@hostjuca:22/home/juca/src/novo_projeto
* [new branch] branchdoze -> branchdoze
Com isso, lá no repositório principal (hostjuca) foi criando um branch chamado branchdoze, e para terminar a operação o Juca (dono do repositório principal) precisa fazer um “merge” do branch “branchdoze” para o branch “master”.
juca@hostjuca:~/src/novo_projeto$ git merge branchdoze
Com isso temos o código que está em hostze e o código que está em hostjuca (o repo principal) sincronizados.
Voltando no tempo…
Lembra que falei que tinhamos duas opções pra sincronizar o código: empurrar ou puxar? Então, o que fizemos até aqui foi empurrar o código de um desenvolvedor para o repositório principal. Vamos fazer o contrário (o repo principal puxa as alterações do dev) só pra ver como fica. Pra isso, vamos voltar o código do repositório principal para a versão anterior as mudanças feitas pelo Zé lá em hostze. Isso é feito com «git reset». A sintaxe é a seguinte:
$ git reset --hard <commit>
Então, será feito o seguitne no repositório principal: primeiro daremos um «git log» pra ver qual o hash do commit que queremos e depois usaremos o git reset para voltar para esta versão. Assim:
juca@hostjuca:~/src/novo_projeto$ git log
commit 2117cfdf7a4ff0683487a33008e3fc5bca42cdbe
Author: Zé Date: Tue Jan 5 15:49:24 2010 -0200
Primeira alteração do Zé
commit 937f17e96ee04e1221783e664d270dda5d87657d
Author: Juca Date: Tue Jan 5 14:37:20 2010 -0200
Só testando o novo branch
commit dc00b38b6beb9db50d8b0ad0fb7e6a80689c80cb
Author: Juca Date: Tue Jan 5 12:41:51 2010 -0200
Primeiro commit do tutorial
juca@hostjuca:~/src/novo_projeto$ git reset --hard 937f17e96ee04e1221783e664d270dda5d87657d
HEAD is now at 937f17e Só testando o novo branch
Com isso temos o nosso repositório principal de volta a época em que o Zé não tinha alterado nada.
Puxando as coisas
Agora vamos sincronizar fazendo com que o repositório principal “puxe” as mudanças do repositório do Zé. Isso será feito com «git pull». A sintaxe é a seginte:
$ git pull ssh://[usuario@]host:[porta] branch_remoto
Então, pro Juca puxar as mudanças do Zé, a coisa fica assim:
juca@hostjuca:~/src/novo_projeto$ git pull ssh://juca@hostze:22/home/ze/src/novo_projeto master
juca@hostze\'s password:
From ssh://hostze:22/home/ze/src/novo_projeto
* branch master -> FETCH_HEAD
Updating 937f17e..2117cfd
Fast forward arquivo2 | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
Como não existia nenhum conflito entre as versões, tudo ocorreu tranqüilamente, e já temos novamente nossos códigos em hostze e hostjuca sincronizados. Bom, isso é só uma amostra do que o git pode fazer, mas o git pode fazer muito mais que isso. Dá uma olhadinha no gitmagic pra você ver. Na minha próxima postagem sobre o git, explico como configurar o git para usar http ao invés de ssh. Então, até lá e divirtam-se!
Criando um túnel reverso com SSH
- publicado em 22 de dezembro de 2009
Essa aqui é uma rapidinha sobre como criar um túnel reverso no ssh. Pergunta: Pra que serve um túnel ssh reverso? Resposta: Eu uso isso pra chegar em uma máquina que não poderia chegar diretamente (máquina atrás de nat e talz…) Vamos lá!
Suponhamos que eu tenha dois hosts distintos (host1 e host2). host1 está atrás do nat e host2 está conectado diretamente na internet. O que faremos aqui é abrir uma conexão ssh de host1 para host2 e deixar o túnel aberto, assim podendo ir de host2 para host1 (adeus nat!). A sintaxe para sair de host1 para host2, deixando o túnel aberto, seria assim:
ssh -R [porta_pra_voltar_pra_host1]:localhost:[porta_ssh_host2] host2
Então, eu estando em host1 faria o seguinte:
juca@host1:~$ ssh -R 2222:localhost:22 host2
Ai, enquanto (e somente enquanto) esta conexão estiver aberta, é possivel conectar de host2 em host1 usando: ssh -p [porta_pra_voltar_pra_host1] localhost Então, eu estando em host2, faria o seguite:
juca@host2:~$ ssh -p 2222 localhost Bom... É isso ai. Molezinha, não?
Instalação e configuração do PostgreSQL no Debian
- publicado em 21 de dezembro de 2009
Essa aqui é uma rapidinha sobre como instalar e configurar o PostgreSQL no Debian.
Primeiro, instalar o banco:
# aptitude install postgresql
Depois de baixar e instalar é hora de configurar. O usário root do nosso banco de dados é o postgres. No processo de instalação foi criado um usuário chamdo postgres também no sistema. Então, nos logaremos com este usuário.
# su postgres
Por padrão, o usuário de banco de dados “postgres” não tem senha, então agora nos logaremos no shell do PostgreSQL para alterar a senha do usuário postgres.
Primeiro, logando no shell…
$ psql
Agora, já no shell do PostgreSQL, vamos alterar a senha do usuário postgres
postgres=# ALTER USER postgres WITH PASSWORD 'qualquersenha';
Esse cara que a gente acabou de configurar ai é o root do banco de dados… A gente não vai ficar usando esse usuário nas nossas aplicações, né? Então! vamos criar um novo usuário.
postgres=# CREATE USER usuario NOCREATEDB NOSUPERUSER NOCREATEROLE PASSWORD 'senha';
Agora, vamos criar uma tabela também
postgres=# CREATE DATABASE minhabase;
Bom, já criamos usário, base de dados… Agora precisamos configurar o modo como os clientes se autenticarão no servidor. Essas configurações se encontram no arquivo pg_hba.conf, que no Debian fica em /etc/postgresql/8.4/main.
OBS: Esse 8.4 aí em cima se refere à versão que estou usando. Se sua versão for diferente, o número também será. Vamos abrir o arquivo e editá-lo.
Como o arquivo é bem comentado não vou me alongar na explicação… Qualquer coisa é só olhar aqui. A primeira coisa que farei aqui é deixar o tipo de autenticação para os usuários locais como md5.
Então, a linha que era assim: local all all ident Ficou assim: local all all md5
Do jeito que as coisas estão, somente usuários locais poderão se conectar ao banco. Então agora vamos fazer umas configurações para que clientes remotos possam se conectar ao banco. O primeiro passo para liberar conexões para clientes remotos é adicionar uma liniha ao pg_hba.conf. A linha seria algo como: host all all 0.0.0.0/0 md5.
Pra finalizar precisaremos também editar o arquivo postgresql.conf, que fica no mesmo diretório que o pg_hba.conf.
No postgresql.conf procure pela linha #listen_addresses = “localhost” e mude para listen_addresses = “*”
Agora é só reiniciar o postgresql…
/etc/init.d/postgresql-8.4 restart
E está tudo pronto!
Pequena introdução ao sqlalchemy
- publicado em 07 de dezembro de 2009
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Este documento é uma rápida introdução ao SQLAlchemy.
#
# SQLAlchemy is the Python SQL toolkit and Object Relational Mapper
# that gives application developers the full power and flexibility of SQL.
#
# It provides a full suite of well known enterprise-level persistence patterns,
# designed for efficient and high-performing database access, adapted into a
# simple and Pythonic domain language.
#
# Ao escrever isso estou usando python 2.6 e sqlalchemy 0.5.5.
# Como exemplo vou organizar a coleção de discos.
m = raw_input("Mostrar sql gerado?[s/n] ")
mostrar = [True, False][m.lower() == 'n']
espera = mostrar
############# PASSO 1 - CRIAR UMA CONEXÃO COM O BANCO DE DADOS. ################
# O banco de dados usado será o sqlite.
# O sqlalchemy usa um objeto 'engine' para se conectar ao banco de dados.
from sqlalchemy import create_engine
#O parametro 'echo = True' faz com que o sql gerado seja mostrado na tela.
engine = create_engine('sqlite:///discoteca.db', echo = mostrar)
########### PASSO 2 - CRIAR AS TABELAS QUE SERÃO USADAS. #######################
#Uma tabela no sqlalchemy é um objeto do tipo Table.
#objetos do tipo Column são usados para definir os campos da tabela.
from sqlalchemy import Table, Column, Integer, String, ForeignKey, MetaData
# MetaData é o objeto responsável pelas queries e orm.
metadata = MetaData()
tabela_bandas = Table('bandas', metadata,
Column('id', Integer, primary_key = True),
Column('nome', String),
Column('lugar', String)
)
#Um disco pode ter mais de uma banda.
tabela_discos = Table('discos', metadata,
Column('id', Integer, primary_key = True),
Column('nome', String),
Column('ano', Integer)
)
tabela_discos_bandas = Table('discos_bandas', metadata,
Column('id', Integer, primary_key = True),
Column('id_banda', Integer, ForeignKey('bandas.id')),
Column('id_disco', Integer, ForeignKey('discos.id')),
)
#Neste exemplo uma música só está em um único disco.
tabela_musicas = Table('musicas', metadata,
Column('id', Integer, primary_key = True),
Column('id_disco', Integer, ForeignKey('discos.id')),
Column('id_banda', Integer, ForeignKey('bandas.id')),
Column('numero', Integer),
Column('nome', String)
)
#Como as tabelas não existem, as criaremos usando a nossa instância de MetaData().
#Nossa engine (criada no passo 1) será passada como parametro.
metadata.create_all(engine)
if espera:
raw_input("\nO SQL gerado foi a criação das tabelas.")
# Conexão com o banco de dados estabelecida, tabelas criadas...
#Agora é hora de definir nossos objetos.
####### PASSO 3 - CRIAR AS CLASSES E MAPEÁ-LAS COM AS TABELAS CRIADAS. #########
#Para mapear as classes com as tabelas usaremos o método mapper()
#A sintaxe do mapper é a seginte: mapper(classe, tabela).
#Com isso, associa-se a classe à tabela.
from sqlalchemy.orm import mapper, relation
class musica(object):
def __repr__(self):
numero = self.numero or 0
nome = self.nome or ''
if self.disco:
disco = self.disco.nome
else:
disco = ''
return """numero: %i, nome: %s, disco: %s""" %(numero, nome, disco)
#mapeando musica com tabela_musicas.
mapper(musica, tabela_musicas)
class banda(object):
def __repr__(self):
nome = self.nome or ''
lugar = self.lugar or ''
return """nome: %s, lugar: %s""" %(nome, lugar)
#mapeando banda com tabela_bandas.
#Definiremos também a relação banda/musica usando relation(),
#'backref' cria a relação também 'do lado contrário'.
#O parâmetro 'properties' cria atributos para a classe que está sendo mapeada.
mapper(banda, tabela_bandas,
properties = {'musicas' : relation(musica, backref = 'banda')}
)
class disco(object):
def __repr__(self):
nome = self.nome or ''
ano = self.ano or 0
if self.bandas:
banda = ','.join([i.nome for i in self.bandas])
else:
banda = ''
return """nome: %s, ano: %s, banda: %s""" %(nome, str(ano), banda)
#Mapeando disco com tabela_discos, onde definiremos também relacionamentos.
#A relação bandas/discos é muitos-para-muitos. Por isso foi passado o parâmetro
#'secondary'.
mapper(disco, tabela_discos,
properties = {'musicas' : relation(musica, backref = 'disco'),
'bandas' : relation(banda,
secondary = tabela_discos_bandas,
backref = 'discos')
}
)
#Já está tudo criado, os objetos mapeados... Vamos brincar com a coisa!
###################### BRINCANDO COM OS NOSSOS OBJETOS ########################
#Primeiro instanciar banda() e cadastrar uma nova banda.
#Repare que os atributos do objeto são as colunas da tabela (da hora, né!) .
nova_banda = banda()
nova_banda.nome = "Tankard"
nova_banda.lugar = "Frankfurt"
#Bom, uma nova banda foi criada aí, mas ainda não foi salva no banco.
#Para salvar no banco usaremos um objeto 'session' que será criado com sessionmaker
#Nossa 'session' será associada à nossa 'engine'.
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind = engine)
session = Session()
#Agora, com a session criada, é só adicionar nosso objeto a session...
session.add(nova_banda)
# ...e 'commitar' a coisa.
session.commit()
if espera:
raw_input("\nEste sql é da inserção de uma banda.")
#Pronto, objeto salvo. Agora vamos recuperá-lo.
#Usaremos o método session.query() para fazer isso.
uma_banda = session.query(banda).filter(banda.nome == "Tankard").first()
if espera:
raw_input("\nEste aqui é a recuperação de uma banda.")
#Bom, vamos criar um disco.
novo_disco = disco()
novo_disco.nome = "The Morning After"
novo_disco.ano = 1988
session.add(novo_disco)
session.commit()
#Um disco tem músicas, não?
musicas = ['Intro', 'Commandment', 'Shit-faced', 'TV Hero', 'F.U.N.',
'Try Again', 'The Morning After', 'Desperation',
'Feed the Lohocla', 'Help Yourself', 'Mon Cheri', 'Outro']
i = 1
for m in musicas:
nova_musica = musica()
nova_musica.nome = m
nova_musica.banda = uma_banda
nova_musica.numero = i
i += 1
#Lembra do relation(), backref e tal que falei lá em cima? Então, olha aí!
#O atributo nova_musica.disco aí embaixo foi criado com eles.
nova_musica.disco = novo_disco
session.add(nova_musica)
session.commit()
#Usando novamente um atributo criado na configuração do mapper...
uma_banda.discos.append(novo_disco)
#Bom, vamos cadastrar mais umas coisas aí pra entender direitinho como funciona.
rdp = banda()
rdp.nome = u"Ratos de Porão"
rdp.lugar = u"São Paulo"
cl = banda()
cl.nome = u"Cólera"
cl.lugar = u"São Paulo"
pk = banda()
pk.nome = u"Psykóze"
pk.lugar = u"São Paulo"
fc = banda()
fc.nome = u"Fogo Cruzado"
fc.lugar = u"São Paulo"
outro_disco = disco()
outro_disco.nome = "Sub"
outro_disco.bandas.append(rdp)
outro_disco.bandas.append(cl)
outro_disco.bandas.append(pk)
outro_disco.bandas.append(fc)
session.add(outro_disco)
#session.commit()
musicas_sub = [(u'Parasita', rdp), (u'Vida Ruim', rdp), (u"Poluição Atômica", rdp),
(u"X.O.T.", cl), (u"Bloqueio Mental", cl),
(u"Quanto Vale a Liberdade", cl), (u"Terceira Guerra Mundial", pk),
(u"Buracos Suburbanos", pk), (u"Fim do Mundo", pk),
(u"Desemprego", fc), (u"União entre os Punks do Brasil", fc),
(u"Delinqüentes", fc), (u"Não Podemos Falar", rdp),
(u"Realidades da Guerra", rdp), (u"Porquê?", rdp), (u"Histeria", cl),
(u"Zero zero", cl), (u"Sub-ratos", cl), (u"Vítimas da Guerra", pk),
(u"Alienação do Homem", pk), (u"Desilusão", pk), (u"Inimizade", fc),
(u"Punk Inglês", fc), (u"Terceira Guerra", fc)]
i = 1
for m in musicas_sub:
nova_musica = musica()
nova_musica.nome = m[0]
nova_musica.banda = m[1]
nova_musica.numero = i
session.add(nova_musica)
session.commit()
nova_musica.disco = outro_disco
i += 1
#Agora que já criamos as paradas, vamos ver...
bandas = session.query(banda).all()
for b in bandas:
print "Banda: " , b.nome
for d in b.discos:
print " Disco: ", d.nome
for m in d.musicas:
if m.banda.id == b.id:
print " Música: ", m.nome