2010-09-26

Script: playlist - pare de procurar, peça o que você quer ouvir




Eu gosto de música, gosto mesmo.

Quando eu era criança lá em casa era assim: meu pai gostava de rock e jovem guarda, minha mãe de sambas antigos e mpb, minha irmã conhecia todos os sucessos de todos os artistas das principais rádios da cidade. Quando tinha uma música que ela gostava muito, deixava o gravador de K7 em REC, PLAY e PAUSE, só esperando a hora que o locutor iria anunciar a música do momento, aí ela soltava o PAUSE um pouco antes e encontrar o timming pra cortar - e precisava porque as rádios começaram a dar fade in/fade out cruzando o final de um sucesso como começo de um jabaculê, sem falar quando o locutor anunciava o nome da estação do meio da música; então a gravação ficava meia boca, o locutor no começo, uma propaganda no final, mas bastava levar a fita pra um amigo dono de um poderoso stereo double deck  e o cara limpava a gravação em uma segunda fita. Na década de 80 era assim e o pessoal já dizia que as fitas K7 e o VHS iriam acabar com a indústria do entretenimento. Mas não acabou.

Naquela época eu tinha herdado de meu falecido avô, uma caixa de vinil com os dizeres dourados em caixa-alta "a história da música clássica". Aquilo era o meu tesouro e eu o ouvia sem parar, era totalmente diferente do que eu estava habituado, era forte, volumoso, inesperado. Veja só que coisa curiosa, na caixa deviam ter uns 21 discos, parece pouco hoje, mas eu levei anos para ouvir todos os 21.
Pensando nisso lembrei de uma conversa com um amigo historiador, ele comentou que na alta idade média quando alguém se referia à sua biblioteca de casa falava em uns 20 volumes. Curioso como mudam as referências. Tá certo que eles sabiam estes livros em seus coraç de cor e hoje em dia a gente mal lembra o que almoçou...

O CD só começou a se popularizar na virada da década de 90 e praticamente toda a minha coleção data daquela época: mpb, rock, metal, techno, uns clássicos mais arrojados e jazz, muito jazz. As lojinhas obscuras, importadores sinistros, os discos raros... Só tinha um probleminha, as mídias de cd (que diziam que durariam 100 anos) tinham uma durabilidade tão ruim quanto a fita k7. Enquanto as fitas cassete tendiam a se desmagnetizar com o tempo e os cds a descascar, tudo o que o vinil pedia era um espanador.


Toda mídia é um suporte material e toda matérica tende a sua decomposição. Mas o direito a ouvir uma determinada música foi adquirido quando o comprei, se tivesse comprado a mídia, não teria direito a reclamar quando a fita fosse inaudível.


- Sinto muito senhor, mas não posso trocar a sua mídia porque o que senhor comprou foi um rolo de fita magnética em um caixa de plástico e é exatamente um rolo de fita magnética em um caixa de plástico que você tem em mãos.



O que foi comercializado foi uma música, eu adquiri o direito de poder ouvi-la e tomar todas as ações de modo a preservar este direito, portanto se ela não durar em um cd, eu posso gravá-la em um fita, ou em outro cd, ou jogar em um gravador de vinil usb, ou deixar uma cópia de segurança em um arquivo digital.


Ah, o MP3: enquanto eu puder espetar uma HD nova em minha máquina, meus arquivos serão perpétuos. A primeira coisa que fiz foi gravar toda a minha coleção em 64Kbps, depois 96Kbps, 128Kbps, com VBR, em 256Kbps. Depois os discos de meus parentes, amigos, vizinhos... Até chegar um tal de napster e audio galaxy, fast track, torrents... Foram uns anos frenéticos e deve fazer uns 4 anos que praticamente não baixo mais nada. É hora de ouvir a coleção.
E aí, por melhor organizada que ela possa estar, começa a ficar chato encontrar uma música determinada. De vez em quando nem sei o que tenho, afinal são


$ find /mnt/arquivos/music/ -type f \( -iname '*[afmow][aglmpv4][acegiv34]' -print \) -o \( -iname '*[mf][pl][ea][gc]' -print \) | wc -l
20533


arquivos. Durante estes quase 15 anos de música digital, usei diversos gerenciadores de coleção. Todos que testei sofrem do mesmo problema, a coleção fica ordenada sob aquele software e uma vez que ele se tornar obsoleto, ou que o arquivo for aberto por outro programa, lá se foi a ordem. Então prefiro ordenar utilizando diretórios da seguinte forma:


[ESTILO]/[AUTOR]/[ÁLBUM]/[faixa]


Não quero procurar uma faixa quando sei seu nome, quero digitar "hendrix experience" ou "chico 78" e ouvir o disco procurado. Então fiz este pequeno script, modifique-o para seu sistema porque não fiz um configurador. Enfim,


se você souber o nome do arquivo, use a opção -f
$ playlist -f favorite things
$ playlist -f purple haze
$ playlist -f pelas tabelas

se você quiser tocar todas as faixas sob diretório contendo o padrão "Miles" e "Coltrane", basta
$ playlist -a miles coltrane
$ playlist -a ult exp
$ playlist -a goldberg
$ playlist -a bwv 988

Se você quiser tocar todas as faixas de áudio sob um certo diretório (recursivamente), basta
$ playlist -d diretório
$ playlist -d /mnt/torrents

Você pode ver e baixar o código aqui: http://pastebin.com/UNJc4wNa

[]s
/dev/movebo

2010-09-13

Script: receba seu IP externo via gmail, ou ainda, automatize seu sistema com o auxílio de e-mails

Muitas vezes precisamos acessar nossas máquinas remotamente (via SSH principalmente), mas como aqui no Brasil os IPs estáticos são absurdamente caros e os dinâmicos podem facilmente mudar: perda de sinal do modem, falta de energia, problemas no provedor de acesso... precisamos de algum modo simples e transparente de obtê-lo.
É, eu sei, existe o NoIP e o DynDNS, mas esta mesma solução pode resolver outros problemas para outros usuários, que simplesmente não consigo prever.
Então, mãos à obra pessoal.

Nossa tarefa será dividida em 3 partes:

1. Instalar o software de envio de e-mails;
2. Criar os scripts para ler automaticamente os e-mails;
3. Criar um script para ser executado pelo boot e pelo cron.


Índice


1. Instalando o msmtp;
    1.1 Gerando os certificados PEM;
    1.2 Configurando o .msmtprc;
2. Lendo os e-mails com o wget;
    2.1 Acessando o servidor remoto;
3. Criando um script de checagem e envio;
  3.1 O script rc.mailMyIp.



1 - Enviando os e-mails: msmtp + gmail


O msmtp é um cliente capaz de enviar e-mails para qualquer servidor SMTP, é um bom substituto simplificado para o sendmail.

Sua documentação pode ser lida aqui:
  < http://msmtp.sourceforge.net/doc/msmtp.html >

O código-fonte pode ser baixado aqui:
     < http://sourceforge.net/projects/msmtp/

Instalação 
$ wget http://downloads.sourceforge.net/project/msmtp/msmtp/1.4.21/msmtp-1.4.21.tar.bz2
$ tar xjvf msmtp-1.4.21.tar.bz2
$ cd msmtp-1.4.21
$ ./configure
$ make
# make install

Se você estiver no Debian ou algum variante rode: 
$ sudo apt-get install `apt-cache search msmtp | awk '{print $1}'`

Para configurar o msmtp eu me baseei neste ótimo artigo do Andrew's Corner. Como agora o gmail só permite POP e SMTP via conexão SSL, precisaremos gerar dois certificados PEM (Privacy-enhanced Electronic Mail). Vamos lá.


1.1 - Gerando os certificados PEM


O Andrew criou um script em Perl para gerarmos localmente os certificados e só me levou meia hora para configurar todas os módulos que o Perl necessitava. Então, por caridade, pus o código abaixo, é só copiar e colar:

$ mkdir -pv $HOME/.certs && cat > $HOME/.certs/Equifax_Secure_CA.pem << FIM
-----BEGIN CERTIFICATE-----
MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
UCemDaYj+bvLpgcUQg==
-----END CERTIFICATE-----
FIM
$ cat > $HOME/.certs/Thawte_Premium_Server_CA.pem << FIM
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
70+sB3c4
-----END CERTIFICATE-----
FIM

Hora de dizer ao openssl que temos os certificados:
$ c_rehash $HOME/.certs/

OK, tudo pronto para configurar o .msmtprc.



1.2 - Configurando o .msmtprc


Bom, criados os certificados, é hora de fazer nosso arquivo de configuração.
Para evitar confusão entre o que é variável, função, comando e dados a serem preenchidos, o arquivo será configurado para o Zé abaixo.
Mude para seus próprios dados.
Eis, aí o Zé:
Endereço no gmail:zeh@gmail.com
Senha do gmail:53nH*
USER: zeh
HOSTNAME:NAVI

E seu arquivo de configuração:
$ cat > $HOME/.msmtprc << FIM
account default
host smtp.gmail.com
port 587
from zeh@gmail.com
tls on
tls_starttls on
#tls_trust_file /home/zeh/.certs/Thawte_Premium_Server_CA.pem
tls_trust_file /home/zeh/.certs/Equifax_Secure_CA.pem
auth on
user zeh@gmail.com
password 53nH*
logfile ~/.msmtp.log
FIM
$ chmod 600 $HOME/.msmtprc

Note que o chmod é muito importante já que não queremos que outros usuários possam ler nossa senha.
Vamos testar para ver se deu tudo certo:
$ echo -e "Subject: Teste 1\n\nCan you read me?" | msmtp zeh@gmail.com

Veja em sua caixa de entrada se o e-mail chegou.
Em casa ele leva menos de 5 segundos para enviar o e-mail.

Agora que já podemos enviar os e-mails, vamos ver como lê-los.



2 - Lendo e-mails com o wget


Há muitas formas diferentes de ler e-mails pelo bash, eu vou usar uma função pouco explorada do gmail, são os Atom Feeds.
Eles podem ser naturalmente acessados via https através de seu login e senha. No caso do Zé é só jogar a URL abaixo no navegador:

https://zeh:53nH*@mail.google.com/mail/feed/atom

O mesmo efeito pode ser obtido sem um navegador através do auxílio do wget:

$ /usr/bin/wget --secure-protocol=TLSv1 --timeout=3 -t1 -q -O - https://zeh:53nH*@mail.google.com/mail/feed/atom --no-check-certificate

Reparou que a saída está em XML? Se o e-mail enviado for bem padronizado será fácil analisá-lo. Nosso objetivo é fazer algo como:

Subject: NAVI has booted, check your IP
NAVI was booted at 2010-09-12 23:51:15
NAVI IP=207.135.111.25

Um grep 'IP=' no comando acima bastaria para retornar
<summary>NAVI was booted at 2010-09-12 23:51:15 NAVI IP=207.135.111.25</summary>

Mas este sed consumirá muito menos processos:
sed '/NAVI\ IP/!d;s/.*=//g;s/<.*//g;q'

Ele se divide em quatro partes:
/NAVI\ IP/!dNão apague a linha que contiver o padrão NAVI(espaço)IP
s/.*=//gApague tudo do 'igual' para trás
s/<.*//gApague tudo do início da tag '<' para frente
qPegue apenas a primeira linha (o último e-mail) e saia (quit)
Por fim, para não ficar com a senha em um script, simplemente compilei a chamada em C em um arquivo naviip.c:
#include <stdio.h>
#include <stdlib.h>

int main() {

    system( "/usr/bin/wget --secure-protocol=TLSv1 --timeout=3 -t1 -q -O - https://zeh:53nH*@mail.google.com/mail/feed/atom --no-check-certificate | sed '/NAVI\ IP/!d;s/.*=//g;s/<.*//g;q'" );
    return 0;
}

Compile assim:
$ gcc naviip.c -Wall -ansi -o naviip

Teste o programa:
$ ./naviip

De preferência jogue-o em algum lugar do seu PATH.
$ echo $PATH

No Slackware o diretório $HOME está incluído.
Pessoalmente gosto de:
$ mkdir -pv $HOME/bin
$ echo -e 'PATH=$PATH:$HOME/bin\nexport PATH' >> $HOME/.bashrc
$ source $HOME/.bashrc
e vou supô-lo de agora em diante.



2.1 - Acessando o servidor remoto


É claro que não queremos manipular o endereço nós mesmos, um código deve fazer isso.
É mais rápido, é mais fácil.

Este script deve lhe ajudar:
$ curl http://pastebin.com/download.php?i=upi4gMG4 | sed 's/.$//' > $HOME/bin/sshome && chmod 700 $HOME/bin/sshome

Repare que por muita ou pouca paranóia eu configurei meu SSH para escutar atrás de uma porta não-padrão. Normalmente usamos a porta 22, escolhi outra aleatória, a 2247.
Seria interessante fazer um script no servidor para alterar aleatoriamente esta porta e informá-la no e-mail, melhor ainda seria usar o iptables para fazer um Port-Knocking! (TODO ;^)
Repare também que o cliente só tentará se conectar no servidor se realmente houver um SSH escutando atrás daquela porta, o que evita a tentativa infrutífera de acesso a outra máquina que, pelos motivos mais diversos, está agora com nosso antigo IP.



3 - Criando o script de checagem e envio


No Slackware para que um script seja executado por último lugar no boot, duas coisas são necessárias:
  1. Que ele seja chamado pelo /etc/rc.d/rc.local
  2. Que ele seja executável

Adicione as linhas abaixo em seu /etc/rc.d/rc.local como root
if [ -x /etc/rc.d/rc.mailMyIp ]; then
   . /etc/rc.d/rc.mailMyIp start
fi

E vamos criar o rc.mailMyIp.
Há 3 técnicas que gostaria de mencionar:
  1. Na função MSG() envio os dados para um arquivo. Talvez você prefira comparar o IP atual com o que está no arquivo.
    No dia-a-dia achei mais fácil comparar sempre com o que está legível no e-mail, vai que você deleta a mensagem...
  2. Eu obtenho o IP externo na linha 45:
    IP=`curl -s http://myip.com.br/index2.php | sed '/Seu\ IP/!d;s/.*\IP://g;s/<.*//g;s/\ //g'`
    Basicamente uso o curl para acessar um site que informa meu IP e parseio o endereço da mesma forma que fizemos com o e-mail.
  3. A estratégia para enviar o e-mail é a seguinte:
    1. A placa de rede deve ter um endereço válido (em casa é 192.x.y.z, por isso a linha 52);
    2. Então na linha 57 damos 3 tiros de ping (-l3 -w1) para o google e contamos quantos chegam.
      1. Dê preferência a usar o IP, porque em caso de DNS inacessível, o tempo de espera cai bastante. Caso o DNS esteja DISPONÍVEL há um ganho de 17% (OK, 0.192s em média).
      2. Se nenhum ping chegar, não tem internet. Desencane do resto.
    3. Se o ping chegou, busque o IP externo.
    4. Pegue o IP lá do e-mail e compare os dois.
    5. Se forem iguais não há nada a fazer.
    6. Se forem diferentes envie o e-mail.
    7. A versão start é para ser usada no boot, a versão check pelo cron.



3.1 - O script rc.mailMyIp


Preciso deixar colorido o que é para mudar?
Comece pelo ADDRS.
Cheque a linha 24.
Onde você pôs seu naviip (linhas 80, 106)?
O que você acha posso fazer para melhorar isso?
Uma cópia deste script está aqui: http://pastebin.com/B4YHkiHA