Quando a computação em nuvem da Amazon Web Services surgiu, um dos primeiros produtos a serem oferecidos foi o S3, que permite armazenar arquivos em um storage distribuído. No S3, cada arquivo é um objeto compartilhado entre vários servidores, distribuindo entre eles cópias de segurança.
Existem algumas maneiras para se manipular um storage S3. A AWS fornece uma interface API para conversar com seus serviços, e é através desta API que diversos programas conversam com o S3. Inclusive, o próprio gerenciador web é feito em cima dessa API principal. Por ser uma API pública, qualquer pessoa pode fazer programas ou interfaces para trabalhar com o S3.
s3cmd
O s3cmd é um programa de linha de comando pra Linux que implementa a API do S3 e faz as seguintes operações:
- Lista os storages S3 (chamados buckets) e seus conteúdos;
- Cria e remove buckets;
- Puxa (GET) e manda (PUT) arquivos;
- Tem um modo de sync parecido com o rsync;
- Permite armazenar dados criptografados.
Ou seja, dá pra fazer muita coisa com o S3. A ferramenta é bastante usada principalmente para enviar backups para um storage. Em termos de enviar e pegar arquivos, o s3cmd é uma ótima pedida. Ele trabalha usando o método nativo do S3 e por isso todos os arquivos são objetos, assim como o S3 implementa. Digo isso porque há outras ferramentas que implementam um sistema de arquivos diferente da implementação nativa do S3 e com isso ganham vantagens e desvantagens: apesar do sistema de arquivos poder ser montado em um diretório, ter controle de permissões, diretórios, poder ser acessado como qualquer outro programa diretamente do S3, entre outras vantagens, o sistema fica dependente da ferramenta e não é compatível com a API de objetos normais.
Em outras palavras, se você estiver procurando algo simples para mandar, receber e fazer syncs de arquivos, pode usar o s3cmd que ele é a ferramenta certa. Mas se você for querer algo mais complexo para usar com outros programas, tem que experimentar outras ferramentas como o s3ql ou s2fs.
Este tutorial segue a versão s3cmd 1.0.1.
Instalação
Para algumas distribuições, o s3cmd já está disponível empacotadinho, bonitinho e prontinho pra usar. Neste caso:
No Fedora / Fedora EPEL (CentOS e RHEL):
yum install s3cmd
No Ubuntu / Debian:
apt-get install s3cmd
Mas se por acaso não tiver os pacotes nos repositórios que você configurou, basta incluir o repositório do próprio s3cmd e instalar. Visite a página de Downloads de pacotes e repositórios do s3cmd.
Se preferir pegar o pacote do código-fonte (o s3cmd é feito em Python, então nem precisa compilar), é bem fácil. Basta baixar o arquivo do código fonte aqui.
No caso de pegar o pacote do código-fonte, você pode:
- (Recomendado) Executar python setup.py install para fazer o python instalar tudo corretamente;
- Executar a ferramenta no diretório que você descompactou;
- Copiar o executável (cp s3cmd /usr/local/bin) e a página de manual (cp s3cmd.1 /usr/local/share/man/man1) pro sistema;
Configuração
Uma vez instalado o s3cmd, é fácil configurar. Com seu usuário, digite o seguinte:
s3cmd --configure
Esse comando irá iniciar a configuração interativa do programa, onde você precisa colocar as informações:
- Access Key e Secret Key – São as chaves de segurança do seu usuário na AWS (criado no IAM);
- Encryption Password – É uma senha grande para criptografar os arquivos via GPG, caso você queira;
- Use HTTPS protocol – Usar HTTPS (SSL) ao invés de HTTP texto puro, altamente recomendado colocar Yes;
Respondida essas perguntas básicas, o programa ainda testa se sua configuração está correta e consegue acessar os buckets S3 e pergunta se deseja salvar a configuração que você acabou de fazer (óbvio que você vai querer!). Quando salva a configuração, ela fica no caminho:
$HOME/.s3cfg
Onde $HOME é, obviamente, o seu diretório HOME.
Durante algumas configurações, o teste para ver se a configuração funciona pode falhar mesmo se a Access Key e Secret Key forem corretas. Para testar a configuração, o s3cmd manda listar os buckets disponíveis no S3. Se as chaves que você estiver usando só permitem você escrever em um bucket, provavelmente o teste irá falhar (pois ele não pode listar o resto dos buckets). Neste caso, ignore o teste na configuração e siga adiante.
Usando
Com tudo configurado fica muito fácil usar o s3cmd. Vamos lá!
Criando um bucket:
$ s3cmd mb s3://devin-teste Bucket 's3://devin-teste/' created
Agora vou listar todos os buckets:
$ s3cmd ls 2013-05-20 22:42 s3://devin-backup 2013-05-20 22:42 s3://devin-img 2013-05-20 22:41 s3://devin-teste
Colocando (PUT) um arquivo no bucket devin-teste:
$ s3cmd put devin_logo_avatar.png s3://devin-teste devin_logo_avatar.png -> s3://devin-teste/devin_logo_avatar.png [1 of 1] 777403 of 777403 100% in 8s 84.88 kB/s done
Listando agora o conteúdo do bucket devin-teste:
$ s3cmd ls s3://devin-teste 2013-05-20 22:44 777403 s3://devin-teste/devin_logo_avatar.png
Pegando (GET) o arquivo:
$ s3cmd get s3://devin-teste/devin_logo_avatar.png s3://devin-teste/devin_logo_avatar.png -> ./devin_logo_avatar.png [1 of 1] 777403 of 777403 100% in 6s 111.08 kB/s done
Mandando outro arquivo e logo depois removendo:
$ s3cmd put httpd.conf s3://devin-teste httpd.conf -> s3://devin-teste/httpd.conf [1 of 1] 11858 of 11858 100% in 3s 3.79 kB/s done $ s3cmd del s3://devin-teste/httpd.conf File s3://devin-teste/httpd.conf deleted
Agora um sync! Sincronizar o diretório /etc/httpd no bucket devin-backup:
$ s3cmd sync /etc/httpd s3://devin-backup /etc/httpd/conf.d/README -> s3://devin-backup/httpd/conf.d/README [1 of 19] 366 of 366 100% in 1s 185.84 B/s done /etc/httpd/conf.d/autoindex.conf -> s3://devin-backup/httpd/conf.d/autoindex.conf [2 of 19] 2893 of 2893 100% in 1s 1500.63 B/s done /etc/httpd/conf.d/deflate.conf -> s3://devin-backup/httpd/conf.d/deflate.conf [3 of 19] 769 of 769 100% in 1s 392.22 B/s done /etc/httpd/conf.d/errors.conf -> s3://devin-backup/httpd/conf.d/errors.conf [4 of 19] 118 of 118 100% in 1s 59.14 B/s done /etc/httpd/conf.d/expires.conf -> s3://devin-backup/httpd/conf.d/expires.conf [5 of 19] 320 of 320 100% in 1s 164.55 B/s done /etc/httpd/conf.d/php.conf -> s3://devin-backup/httpd/conf.d/php.conf [6 of 19] 691 of 691 100% in 1s 346.27 B/s done ...cortando... /etc/httpd/conf/magic -> s3://devin-backup/httpd/conf/magic [19 of 19] 13077 of 13077 100% in 2s 5.20 kB/s done Done. Uploaded 38604 bytes in 37.1 seconds, 1040.47 B/s
O comando sync funciona igual ao rsync. No nosso caso, qualquer modificação que seja feita no diretório /etc/httpd, vai ser replicada para o S3 quando eu executar o comando sync novamente.
Agora vou remover o bucket vazio (se tiver algo dentro, ele não remove):
$ s3cmd rb s3://devin-img Bucket 's3://devin-img/' removed
Essas são as operações básicas que a maioria dos usuários s3cmd precisam.
Objetos acessíveis publicamente
Todos os objetos do S3 podem ser acessíveis publicamente através de um servidor web da própria Amazon AWS. Por padrão, os objetos que você coloca no bucket S3 são private (privado), ou seja, não acessíveis por esse servidor Web. Se você mudar a ACL do arquivo para public ele vai ficar disponível.
Por exemplo, para configurar aquele arquivo que já mandamos como público:
$ s3cmd setacl --acl-public s3://devin-teste/devin_logo_avatar.png
Sendo público, ele fica disponível na URL:
- http://
.s3.amazonaws.com (no exemplo, seria http://devin-teste.s3.amazonaws.com/devin_logo_avatar.png
Se você quiser já mandar um arquivo, basta usar o –acl-public no comando put:
$ s3cmd put --acl-public httpd.conf s3://devin-teste httpd.conf -> s3://devin-teste/httpd.conf [1 of 1] 11858 of 11858 100% in 2s 4.53 kB/s done Public URL of the object is: http://devin-teste.s3.amazonaws.com/httpd.conf
Criptografia
Ao configurar com o s3cmd –configure, uma das perguntas é uma senha para criptografar arquivos. Essa senha fica guardada no .s3cfg e tem como objetivo mandar os arquivos para o S3 criptogragados de forma transparente. Em outras palavras, o s3cmd executa o GPG em seus arquivos, criptografando com a senha, e manda o resultado pro s3. Para baixar arquivos criptografados ele faz a mesma coisa, baixa e depois descriptografa com o GPG+senha.
$ s3cmd put -e /etc/passwd s3://devin-teste /tmp/tmpfile-M575hbawQldKmMMpho7X -> s3://devin-teste/passwd [1 of 1] 1010 of 1010 100% in 2s 399.90 B/s done
Repare que ele transferiu o arquivo /tmp/tmpfile-M575hbawQldKmMMpho7X, que nada mais é que o arquivo que eu quis enviar, só que criptografado. Se você baixar o arquivo por qualquer outra ferramenta, não vai conseguir ver seu conteúdo (experimente pegar o arquivo via navegador, na interface web). Mas se você baixar pelo s3cmd, ele já deixa o arquivo certo novamente:
$ s3cmd get s3://devin-teste/passwd s3://devin-teste/passwd -> ./passwd [1 of 1] 1010 of 1010 100% in 0s 1255.62 B/s done
O sync não possui suporte ao parâmetro -e (–encrypt), por isso, se quiser mandar arquivos criptografados, terá que mandar com o get. Se quiser diretórios e seus conteúdos (recursivamente), use o parâmetro –recursive junto com o put.
Outra forma de criptografar os arquivos é utilizar a própria criptografia da AWS, também chamado de Server Side Encryption (SSE). Neste modo, você manda o arquivo para a API, e ela internamente criptografa e armazena o arquivo. Se você for pegar o arquivo, a própria amazon decriptografa e te manda. Pra usar é bem simples, basta adicionar um header da seguinte forma:
s3cmd put --add-header=x-amz-server-side-encryption:AES256 /etc/passwd s3://devin-teste
Datacenters diferentes
Todos os exemplos até agora manipularam buckets no datacenter us-east-1 (Virgínia do Norte – EUA). Se vocẽ quiser usar qualquer outro datacenter, basta usar o parâmetro –bucket-location como o exemplo abaixo:
Cria um bucket no datacenter em São Paulo:
s3cmd mb --bucket-location=sa-east-1 s3://devin-sp
A partir daí, tudo o que você fizer no bucket devin-sp será armazenado no datacenter em São Paulo.
Outras configurações e opções
Como dito antes, o s3cmd –configure grava os parâmetros no arquivo .s3cfg. Você pode criar várias configurações e colocar em vários arquivos diferentes. Isso é útil, por exemplo, pra quando você tem múltiplas aplicações copiando para o s3, cada um com um usuário diferente (com access keys e secret keys diferentes). Com isso você pode fazer assim:
s3cmd -c /etc/s3cmd/backup.cfg put /etc/passwd s3://devin-backup s3cmd -c /etc/s3cmd/img.cfg put ratos_motoqueiros_de_marte.jpg s3://devin-img
Cada cfg vai ter uma configuração diferente :-)
E por falar em configuração, dando uma olhada no arquivo s3cfg, podemos ver várias opções! Algumas delas que é interessante citar:
- bucket_location: A região (datacenter) padrão dos buckets. Pode ser: us-east-1, us-west-1, sa-east-1, e por aí vai. Nos comandos, corresponde ao parâmetro –bucket-location que falamos antes;
- default_mime_type: Qual o tipo de arquivo (MIME). Para alguns tipos de arquivos, como imagens, o S3 já reconhece e diz que é uma imagem. Mas para todo o resto, o padrão é binary/octet-stream, ou seja, binário. Quando binário, ao tentar servir publicamente, o usuário acaba fazendo download do arquivo. O parâmetro -m no especifica que tipo de arquivo. Exemplo: text/plain faz com que o arquivo seja um arquivo de texto, então aparece no navegador ao invés de fazer download;
- get_continue: Quando for fazer a operação de puxar arquivos (get), se o arquivo existir localmente e estiver pela metade, o s3cmd tenta continuar de onde parou;
- human_readable_sizes: Na hora de listar os arquivos, mostrar seus tamanhos de uma forma mais legível (1K ao invés de 1024);
- reduced_redundancy: No storage distribuído do S3, colocar True nessa opção significa que os arquivos que você enviar pelo s3cmd ficarão com menos máquinas (menos redundância). Por consequencia, a probabilidade de você perder o arquivo aumenta, mas o custo por GB do storage na AWS diminui;
- socket_timeout: Quanto tempo o s3cmd espera para se conectar na API. Para conexões lentas e inconfiáveis, dá pra aumentar esse número;
Para cada uma dessas opções do s3cfg, há um parâmetro de linha de comando. Consulte a página de manual (man s3cmd) para uma referência mais completa.
Possíveis problemas
A grande maioria dos problemas que você pode ter são problemas na hora de conectar na API e durante o envio do arquivo.
Isso significa que se algo cair durante a transferência de algum arquivo, o s3cmd tem que recomeçar. Não é incomum pegar erros de rede durante a transferência, que tentando alguns minutos depois, funcione perfeitamente. São erros bem inconstantes. Por exemplo: ao escrever este tutorial, houve algumas falhas de transferência de arquivos para o datacenter em São Paulo, mas ao tentar uns 10 minutos depois, funcionou perfeitamente.
O s3cmd vai tentando mandar o arquivo até conseguir, aumentando o intervalo de tempo entre uma tentativa e outra, e abaixando a banda utilizada para mandar os arquivos (throttle).
Broken Pipe / Connection reset by peer
$ s3cmd put devin-tirinha.jpg s3://devin-sp devin-tirinha.jpg -> s3://devin-sp/devin-tirinha.jpg [1 of 1] 24576 of 236372 10% in 3s 7.07 kB/s failed WARNING: Upload failed: /devin-tirinha.jpg ([Errno 32] Broken pipe) WARNING: Retrying on lower speed (throttle=0.00) WARNING: Waiting 3 sec... ...corte... devin-tirinha.jpg -> s3://devin-sp/devin-tirinha.jpg [1 of 1] 36864 of 236372 15% in 3s 10.23 kB/s failed WARNING: Upload failed: /devin-tirinha.jpg ([Errno 104] Connection reset by peer) WARNING: Retrying on lower speed (throttle=0.05) WARNING: Waiting 9 sec...
Sua rede está instável! Algo entre a API e o seu computador não está conseguindo manter as conexões. Isso pode ocorrer, mas não tem muito o que se fazer, a não ser esperar o s3cmd tentar mandar de novo e obter sucesso.
Algumas pessoas reportaram que aumentar o parâmetro socket_timeout ajuda nestes problemas. O socket_timeout define o tempo para esperar antes de conectar à API, e o que ocorre geralmente é um erro brusco no meio da transferência.
Arquivos muito grandes (multipart)
O limite para o envio de um único objeto para o S3 é de 5GB. Com o passar do tempo, a própria Amazon resolveu superar esse limite adicionando o recurso de multipart upload. Neste modo, o cliente manda via API vários pedaços de arquivos. Quando todos estes pedaços chegam ao servidor, o próprio S3 junta todas as partes e faz um objeto.
Com o upload em modo multipart, você pode enviar vários pedaços e criar um único objeto de até 5TB, um aumento considerável em relação a 5GB :P
A versão 1.0.1 do s3cmd, utilizada neste tutorial, não suporta uploads multipart.
A versão 1.1.0+, que é beta, já suporta este tipo de envio, então é uma boa pegar o código-fonte e testar, caso precise. Apesar de ser beta, parece que bastante gente já usou e aprovou o bom funcionamento. Usando essa versão, você já tem o suporte ao multipart habilitado por padrão para arquivos maiores que 15MB. Mas você pode mudar, por exemplo…
Enviando um arquivo de 150MB, dividido em pedaços de 5MB (mínimo permitido pela Amazon):
s3cmd put --multipart-chunk-size-mb=5 150mb.img s3://devin-teste
Então, com o multipart habilitado, uma regra recomendável é: sempre use multipart para enviar arquivos a partir de 100MB.