ler a linha completa em um loop do for

Quando efetuamos um for em shellscript, por padrão ele considera como delimitador espaços, quebras de linha ou tabulações, isso gera  uma dor de cabeça quando temos que tratar nomes e arquivos ou diretórios com espaços.

Para melhor compreensão, abaixo temos um diretório com três arquivos:

[email protected]:~/teste$ ls -l
total 0
-rw-rw-r-- 1 felipebraz felipebraz 0 Abr 19 15:41 1.html
-rw-rw-r-- 1 felipebraz felipebraz 0 Abr 19 15:41 teste2.html
-rw-rw-r-- 1 felipebraz felipebraz 0 Abr 19 15:41 teste de arquivo.html

Ao efetuarmos um for, ele vai quebrar o último arquivo nos espaços, retornando 5 registros ao invés de 3.

[email protected]:~/teste$ for i in `ls`; do echo $i; done
1.html
teste2.html
teste
de
arquivo.html

Para solucionar essa questão, podemos utilizar a variável IFS para definir  qual caractere deve ser usado como delimitador.

[email protected]:~/teste$ IFS="\n"
[email protected]:~/teste$ for i in `ls`; do echo $i; done
1.html
teste2.html
teste de arquivo.html

 

Trocar editor padrão no ubuntu

Quando o ubuntu é instalado, o editor padrão em linha de comando é o nano, porém um das primeiras coisas que sempre faço é instalar o vim.

Mas mesmo após instalar o vim, o editor padrão continua sendo o nano. Pra resolver isso é só usar o alternatives pra trocar o default.

sudo update-alternatives --config editor

Exemplo da saída do comando:

    $ sudo update-alternatives –config editor

    There are 5 alternatives which provide `editor’.
    Selection Alternative
    ———————————————–
    1 /usr/bin/vim
    2 /bin/ed
    *+ 3 /bin/nano
    4 /usr/bin/vim.basic
    5 /usr/bin/vim.tiny
    Press enter to keep the default[*], or type selection number:

Basta escolher o editor pelo número e apertar enter. =)

Usuário de SFTP com chroot/jail

Hoje um usuário me pediu acesso ao “ftp” para algumas manutenções que não seriam possível pelo admin do wordpress, e, como bem sabemos, disponibilizar acesso aos arquivos para clientes pode se tornar um inferno caso não seja pensado primeiramente na segurança.

FTP? Nem pensar! Não vou deixar os dados trafegarem nos meus servidores em texto-plano, e usar FTPS iria gerar mais uma preocupação com certificados, datas de expiração etc.

Que tal SFTP? Protocolo criptografado por padrão, sem muita dor de cabeça, integrado direto no sistema operacional, etc ,etc.
Ok, mas e a segurança? Um usuário padrão conectado via SFP fica logado direto na raiz do SO, gerando mais uma preocupação com segurança. Não quero o usuário fuçando nos arquivos do servidor, afinal.

Uma rápida pesquisa e achei algumas alternativas como rssh e rush, mas fiquei horas e horas tentando configurar e testando sem nenhum sucesso, o máximo que consegui foram erros e mais erros.

bom, voltamos então ao oráculo, e eis que surge uma alternativa alterando o subsistema sftp direto no sshd_config que funcionou que é um relógio!

Pra começar, algumas informações importantes:

  • Utilizei como base o ubuntu server 16.04 LTS
  • Nesse ambiente, o arquivo de configuração fica em /etc/ssh/sshd_config, mas isso pode variar se você estiver utilizando outra distro.
  • Normalmente restartar o ssh não derruba sua sessão aberta, mas é bom ficar preparado caso algo errado aconteça
  • No artigo vamos considerar a seguinte situação:
    • Usuário: braz
    • Homedir: /home/braz
    • Todos os comandos são executados como root

E agora, sem mais delongas, mãos de cobra! Digo… Mãos à obra!

Primeiramente, é obrigatório que o diretório /home/braz esteja com usuário e senha root, pra garantir acesso dos usuário do cliente, vamos usar chmod 755.

chown root:root /home/braz
chmod 755 /home/braz

O shell do usuário não precisa (e nem deve) ser /bin/bash, assim deixarei como /bin/false

usermod -s /bin/false braz

A chave aqui será criar um grupo chamado sftponly, todo o usuário nesse grupo sofrerá chroot

groupadd sftponly

Adicionamos o usuário braz ao grupo

gpasswd -a braz sftponly

Agora vamos editar o arquivo sshd_config.
Primeiramente, vamos comentar a seguinte linha (só colocar um # no começo)

Subsystem sftp /usr/lib/openssh/sftp-server

A configuração-chave deve ser sempre depois da declaração do Pam.
Por via das dúvidas, coloque a config no final do arquivo que não tem erro =)

Subsystem sftp internal-sftp
Match group sftponly
     ChrootDirectory /home/%u
     X11Forwarding no
     AllowTcpForwarding no
     ForceCommand internal-sftp

Se tudo esta certo, só restartar o ssh e partir pro abraço!

service ssh restart

backup de sites com wget

Recentemente precisei efetuar backup de um site para leitura offline, tinha feito um script mirabolante com wget e sed, convertendo links etc, mas pesquisando melhor descobri que o proprio wget tem opções pra muita coisa.

O comando que usei foi

wget \
     --recursive \
     --no-clobber \
     --page-requisites \
     --html-extension \
     --convert-links \
     --restrict-file-names=windows \
     --domains website.org \
     --no-parent \
     http://website.org/diretorio/

As opções usadas são:

  • –recursive: backup do site inteiro, de forma recursiva.
  • –domains website.org: não vai seguir nenhum link de fora do domínio especificado.
  • –no-parent: não vai seguir nenhum link que remeta a diretórios anteriores.
  • –page-requisites: obter todos os elementos que compõem a página (imagens, css, etc).
  • –html-extension: usar extensão html.
  • –convert-links: converter links para uso offline.
  • –restrict-file-names=windows: Modificar nomes de arquivos para funcionar em windows
  • –no-clobber: não sobescrever arquvos (para caso o download ser interrompido e ter que recomeçar).

Comandos úteis para o SED

PREENCHIMENTO DE ARQUIVOS:

 # duplicar o tamanho de um arquivo
 sed G

 # duplicar o tamanho de um arquivo que jah contém linhas em branco.
 # O arquivo de saída deve conter não mais que uma linha branca
 # entre linhas de texto
 sed '/^$/d;G'

 # triplicar o tamanho de um arquivo
 sed 'G;G'

 # desfazer a duplicação de tamanho (assume que as linhas de numeração par
 # estejam em branco)
 sed 'n;d'

 # insere uma linha em branco acima de cada linha que contem "regex"
 sed '/regex/{x;p;x;}'

 # insere uma linha em branco abaixo de cada linha que contem "regex"
 sed '/regex/G'

 # insere uma linha em branco acima e abaixo de cada linha que contem "regex"
 sed '/regex/{x;p;x;G;}'

NUMERACÃO:

 # numera cada linha de um arquivo (com alinhamento simples a esquerda). Usar
 # uma tabulação em vez do espaço vai preservar as margens. (veja a observação
 # sobre o '\t' no final desse arquivo)
 sed = arquivo | sed 'N;s/\n/\t/'

 # numera cada linha de um arquivo (números a esquerda, alinhados a direita)
 sed = arquivo | sed 'N; s/^/     /; s/ *\(.\{6,\}\)\n/\1  /'

 # numera cada linha de um arquivo, mas só imprime os números se a linha não
 # estiver em branco
 sed '/./=' arquivo | sed '/./N; s/\n/ /'

 # conta as linhas (emula o "wc -l")
 sed -n '$='

CONVERSÃO DE TEXTO E SUBSTITUIÇÃO:

 # EM AMBIENTE UNIX: converte o caractere de linha nova do DOS (CR/LF) para o 
 # formato Unix
 sed 's/.$//'            # assume que todas as linhas terminam com CR/LF
 sed 's/^M$//'           # no bash/tcsh, pressione Ctrl-V depois Ctrl-M
 sed 's/\x0D$//'         # gsed 3.02.80, mas os scripts acima sao mais simples

 # EM AMBIENTE UNIX: converte o caractere de linha nova do Unix (LF) para
 # o formato DOS
 sed "s/$/`echo -e \\\r`/"            # comando usado com o ksh
 sed 's/$'"/`echo \\\r`/"             # comando usado com o bash
 sed "s/$/`echo \\\r`/"               # comando usado com o zsh
 sed 's/$/\r/'                        # gsed 3.02.80

 # EM AMBIENTE DOS: converte o caractere de linha nova do Unix (LF) para 
 # o formato DOS
 sed "s/$//"                          # método 1
 sed -n p                             # método 2

 # EM AMBIENTE DOS: converte o caractere de linha nova do DOS (CR/LF) para
 # o formato Unix. Só pode ser feito com o sed UnxUtils, versão 4.0.7
 # ou maior. A versão do UnxUtils pode ser identificada pelo parâmetro padrão
 # "--text" que aparece quando o "--help" é usado. De outra forma, mudar
 # os caracteres de linha nova do DOS para o formato Unix não pode ser
 # feito em um ambiente DOS. Use o "tr" para isso.
 sed "s/\r//" arquivo_entrada >arquivo_saida         # sed UnxUtils versão v4.0.7 ou maior
 tr -d \r <arquivo_entrada >arquivo_saida            # tr GNU versão 1.22 ou maior

 # apaga o espaço em branco inicial (espaços, tabulações) do começo
 # de cada linha, puxando o texto para a esquerda
 sed 's/^[ \t]*//'                    # veja a nota sobre o '\t' no final
                                      # deste arquivo

 # apaga o espaço em branco final (espaços, tabulações) do final de cada linha
 sed 's/[ \t]*$//'                    # veja a nota sobre o '\t' no final
                                      # deste arquivo

 # deleta AMBOS os espaços em branco final e inicial de cada linha
 sed 's/^[ \t]*//;s/[ \t]*$//'

 # insere 5 espaços em branco no ínicio de cada linha (faz o offset da página)
 sed 's/^/     /'

 # alinha tudo a direita, numa coluna de 79 caracteres de largura
 sed -e :a -e 's/^.\{1,78\}$/ &/;ta'  # definido como 78 mais 1 espaço

 # centraliza todo o texto no meio de uma coluna de 79 caracteres de
 # largura. No método 1, os espaços no começo da linha são significativos,
 # e espaços em branco são anexados ao final de cada linha. No método 2,
 # os espaços no início de cada linha são descartados ao centralizar
 # a linha e não é adicionado nenhum espaço no final de cada linha.
 sed  -e :a -e 's/^.\{1,77\}$/ & /;ta'                     # método 1
 sed  -e :a -e 's/^.\{1,77\}$/ &/;ta' -e 's/\( *\)\1/\1/'  # método 2

 # substituir (achar e trocar) "foo" por "bar" em cada linha
 sed 's/foo/bar/'             # troca somente a 1a instância de uma linha
 sed 's/foo/bar/4'            # troca somente a 4a instância de uma linha
 sed 's/foo/bar/g'            # troca TODAS as instâncias de uma linha
 sed 's/\(.*\)foo\(.*foo\)/\1bar\2/' # troca o 'próximo-para-último'
 sed 's/\(.*\)foo/\1bar/'     # troca somente a última occorrência

 # substitui "foo" por "bar" SOMENTE nas linhas que contem "baz" 
 sed '/baz/s/foo/bar/g'

 # substitui "foo" por "bar" EXCETO nas linhas que contem "baz"
 sed '/baz/!s/foo/bar/g'

 # troca "scarlet" ou "ruby" ou "pucy" para "red"
 sed 's/scarlet/red/g;s/ruby/red/g;s/puce/red/g'   # na maioria dos seds
 gsed 's/scarlet\|ruby\|puce/red/g'                # somente no GNU sed 

 # reverter a ordem das linhas (emula o "tac")
 # um bug/função do HHsed v1.5 fazia com que as linhas em branco fossem deletadas
 sed '1!G;h;$!d'              # método 1
 sed -n '1!G;h;$p'            # método 2

 # reverte cada caractere em cada linha (emula o "rev")
 sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//'

 # une pares de linhas lado a lado (como o "paste")
 sed '$!N;s/\n/ /'

 # se uma linha termina com uma barra invertida, a próxima linha é
 # anexada a ela
 sed -e :a -e '/\\$/N; s/\\\n//; ta'

 # se uma linha termina com um sinal de igual, ela é anexada a linha
 # anterior e o sinal de "=" é substituído por um espaco simples.
 sed -e :a -e '$!N;s/\n=/ /;ta' -e 'P;D'

 # adiciona vírgulas a strings numéricos, mudando "1234567" para "1,234,567"
 gsed ':a;s/\B[0-9]\{3\}\>/,&/;ta'                     # GNU sed
 sed -e :a -e 's/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/;ta'  # outros seds

 # adiciona vírgulas em números com pontos decimais e sinais de negativo (GNU sed)
 gsed -r ':a;s/(^|[^0-9.])([0-9]+)([0-9]{3})/\1\2,\3/g;ta'

 # adiciona uma linha em branco a cada 5 linhas (após as linhas 5, 10, 15, 20, etc.)
 gsed '0~5G'                  # somente no GNU sed
 sed 'n;n;n;n;G;'             # outros seds

IMPRESSÃO SELETIVA DE CERTAS LINHAS:
 
 # imprime as primeiras 10 linhas de um arquivo (emula o comportamento do "head")
 sed 10q

 # imprime a primeira linha de um arquivo (emula o "head -1")
 sed q

 # imprime as últimas 10 linhas de um arquivo (emula o "tail") 
 sed -e :a -e '$q;N;11,$D;ba'

 # imprime as 2 últimas linhas de um arquivo (emula o "tail -2")
 sed '$!N;$!D'

 # imprime somente a última linha de um arquivo (emula o "tail -1")
 sed '$!d'                    # método 1
 sed -n '$p'                  # método 2

 # imprime somente as linhas que se encaixam na expressão regular 
 # (emula o "grep")
 sed -n '/regexp/p'           # método 1
 sed '/regexp/!d'             # método 2

 # imprime somente as linhas que NÃO se encaixam na regexp (emula o "grep -v")
 sed -n '/regexp/!p'          # método 1, corresponde ao descrito acima
 sed '/regexp/d'              # método 2, sintaxe mais simples

 # imprime a linha imediatamente anterior a expressão regular, mas
 # não a linha contendo a expressão
 sed -n '/regexp/{g;1!p;};h'

 # imprime a linha imediatamente posterior a expressão regular, mas
 # não a linha contendo a expressão
 sed -n '/regexp/{n;p;}'

 # imprime uma linha de contexto antes e depois da expressão regular,
 # com o número da linha indicando onde a expressão regular 
 # aparece (similar ao "grep -A1 -B1")
 sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}' -e h

 # procura e imprime por AAA e BBB e CCC (em qualquer ordem)
 sed '/AAA/!d; /BBB/!d; /CCC/!d'

 # procura e imprime por AAA e BBB e CCC (nessa ordem)
 sed '/AAA.*BBB.*CCC/!d'

 # procura e imprime por AAA ou BBB ou CCC (emula o "egrep")
 sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d    # maioria dos seds
 gsed '/AAA\|BBB\|CCC/!d'                        # somente com o sed GNU

 # imprime um parágrafo se ele possuir AAA (linhas vazias separam os parágrafos).
 # Com o HHsed v1.5 deve ser inserido o 'G;' apos o 'x;', nos 3 scripts abaixo
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;'

 # imprime um parágrafo se ele possuir AAA e BBB e CCC (em qualquer ordem)
 sed -e '/./{H;$!d;}' -e 'x;/AAA/!d;/BBB/!d;/CCC/!d'

 # imprime o parágrafo inteiro se ele possuir AAA ou BBB ou CCC
 sed -e '/./{H;$!d;}' -e 'x;/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d
 gsed '/./{H;$!d;};x;/AAA\|BBB\|CCC/b;d'         # somente com o GNU sed

 # imprime somente as linhas com 65 caracteres ou mais
 sed -n '/^.\{65\}/p'

 # imprime somente as linhas com menos que 65 caracteres
 sed -n '/^.\{65\}/!p'        # método 1, corresponde ao descrito acima
 sed '/^.\{65\}/d'            # método 2, sintaxe mais simples

 # imprime uma parte do arquivo que vai da expressão regular até
 # o final do mesmo
 sed -n '/regexp/,$p'

 # imprime uma parte do arquivo baseada nos números das linhas (linhas 8-12,
 # inclusive)
 sed -n '8,12p'               # método 1
 sed '8,12!d'                 # método 2

 # imprime a linha de número 52
 sed -n '52p'                 # método 1
 sed '52!d'                   # método 2
 sed '52q;d'                  # método 3, eficiente com arquivos grandes

 # começando na linha 3, imprime cada sétima linha
 gsed -n '3~7p'               # somente o GNU sed
 sed -n '3,${p;n;n;n;n;n;n;}' # outros seds

 # imprime um pedaço de arquivo que está entre as duas
 # expressões regulares (inclusive)
 sed -n '/Iowa/,/Montana/p'             # é case sensitive

DELEÇÃO SELETIVA DE CERTAS LINHAS:

 # imprime todo o arquivo EXCETO a parte entre 2 expressões regulares
 sed '/Iowa/,/Montana/d'

 # deleta linhas duplicadas consecutivas de um arquivo (emula o "uniq"). A primeira
 # linha de um conjunto de linhas duplicadas é mantida, o resto é deletada
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # deleta linhas duplicadas não consecutivas. Tome cuidado para nao estourar
 # o tamanho do buffer do espaco de reserva (hold space), ou então use o sed GNU.
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'

 # deleta todas as linhas exceto as linhas duplicadas (emula o "uniq -d").
 sed '$!N; s/^\(.*\)\n\1$/\1/; t; D'

 # deleta as 10 primeiras linhas de um arquivo
 sed '1,10d'

 # deleta a última linha de um arquivo
 sed'$d'

 # deleta as 2 últimas linhas de um arquivo
 sed 'N;$!P;$!D;$d'

 # deleta as 10 últimas linhas de um arquivo
 sed -e :a -e '$d;N;2,10ba' -e 'P;D'   # método 1
 sed -n -e :a -e '1,10!{P;N;D;};N;ba'  # método 2

 # deleta cada oitava linha
 gsed '0~8d'                           # somente no GNU sed
 sed 'n;n;n;n;n;n;n;d;'                # outros seds

 # deleta as linhas que combinarem com padrão
 sed '/padrao/d'

 # deleta TODAS as linhas em branco de um arquivo (o mesmo que "grep '.' ")
 sed '/^$/d'                           # método 1
 sed '/./!d'                           # método 2

 # deleta todas as linhas brancas CONSECUTIVAS de um arquivo exceto a primeira;
 # ainda deleta todas as linhas em branco do início e fim do arquivo (emula o
 # "cat -s")
 sed '/./,/^$/!d'          # método 1, permite 0 brancos no topo, 1 no
                           # final do arquivo
 sed '/^$/N;/\n$/D'        # método 2, permite 1 branco no top, 0 no
                           # final do arquivo

 # deleta todas as linhas em branco CONSECUTIVAS do arquivo, exceto as 2 primeiras:
 sed '/^$/N;/\n$/N;//D'

 # deleta todas as linhas em branco iniciais, no início do arquivo
 sed '/./,$!d'

 # deleta todas as linhas em branco finais, no final do arquivo
 sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'  # funciona com todos os sed
 sed -e :a -e '/^\n*$/N;/\n$/ba'        # o mesmo, exceto gsed 3.02*

 # deleta a última linha de cada parágrafo
 sed -n '/^$/{p;h;};/./{x;/./p;}'

APLICAÇÕES ESPECIAIS:

 # remove overstrikes nroff (caracter, backspace) das man pages. O comando
 # 'echo' pode precisar da opção -e se você usar Unix System V ou uma
 # shell bash
 sed "s/.`echo \\\b`//g"    # as aspas duplas são necessárias em ambiente Unix
 sed 's/.^H//g'             # no bash/tcsh, pressione Ctrl-V e depois Ctrl-H
 sed 's/.\x08//g'           # expressão hexadecimal para o sed v1.5

 # mostra as mensagens de cabeçalho de um Usenet/e-mail
 sed '/^$/q'                # deleta tudo após a primeira linha em branco

 # mostra o corpo da mensagem de um Usenet/e-mail
 sed '1,/^$/d'              # deleta tudo até a primeira linha em branco

 # mostra o cabeçalho Subject, mas remove a porção inicial "Subject :"
 sed '/^Subject: */!d; s///;q'

 # pega o cabeçalho de endereço de resposta 
 sed '/^Reply-To:/q; /^From:/h; /./d;g;q'

 # verifica o endereço de maneira correta. Pega o endereço de e-mail
 # através da 1a linha do cabeçalho de endereço de retorno (veja
 # o script acima)
 sed 's/ *(.*)//; s/>.*//; s/.*[:<] *//'

 # adiciona um sinal de maior com um espaço a cada linha (citação de uma
 # mensagem)
 sed 's/^/> /'

 # deleta o sinal de maior e o espaço de cada linha (remove a
 # citação de uma mensagem)
 sed 's/^> //'

 # remove a maioria das tags HTML (acomoda tags de múltiplas linhas)
 sed -e :a -e 's/<[^>]*>//g;/</N;//ba'

 # extrai binários uuencoded com múltiplos pedaços, removendo informações
 # estranhas/extras, fazendo com que só a parte uuencoded permaneça. Os 
 # arquivos devem ser passados ao sed na ordem correta. A versão 1 pode
 # ser executada a partir da linha de comando; a versão 2 pode ser
 # executada a partir de um shell script Unix. (Modificado de um
 # script criado por Rahul Dhesi.)
 sed '/^end/,/^begin/d' arquivo1 arquivo2 ... arquivoX | uudecode   # vers. 1
 sed '/^end/,/^begin/d' $* | uudecode                      # vers. 2

 # Ordena parágrafos de arquivos alfabeticamente. Parágrafos são separados
 # por linhas em branco. O GNU sed usa o \v como tabulação vertical, ou qualquer
 # caracter único serve.
 sed '/./{H;d;};x;s/\n/={NL}=/g' file | sort | sed '1s/={NL}=//;s/={NL}=/\n/g'
 gsed '/./{H;d};x;y/\n/\v/' file | sort | sed '1s/\v//;y/\v/\n/'

 # zipa cada arquivo .TXT individualmente, deletando o arquivo fonte
 # e definindo o nome de cada .ZIP para o nome base do arquivo .TXT.
 # (no DOS: o comando "dir /b" retorna nomes de arquivo reduzidos e em caixa alta).
 echo @echo off >zipup.bat
 dir /b *.txt | sed "s/^\(.*\)\.TXT/pkzip -mo \1 \1.TXT/" >>zipup.bat

USO TÍPICO: O sed pega um ou mais comandos de edição e aplica todos eles,
em sequência, a cada linha de entrada. Após todos os comandos terem sido
aplicados a primeira linha de entrada, ela é jogada para a saída e a 
segunda linha de entrada começa a ser processada, recomeçando o ciclo.
Os exemplos acima assumem que a entrada venha do dispositivo padrão  (por exemplo,
o console, onde  normalmente a entrada é via pipe). Um ou mais nomes de 
arquivo podem ser passados na linha de comando se a entrada não vier da
entrada padrão. A saída é mandada para a saída padrão (a tela). Assim:

 cat arquivo | sed '10q'        # usa a entrada via pipe
 sed '10q' arquivo              # tem o mesmo efeito, mas evita o uso do "cat"
 sed '10q' arquivo > novo-arquivo    # redireciona a saída para o disco

Para instruções de sintaxe adicionais, incluindo a maneira de aplicar
comandos de edição a partir de um arquivo no disco, ao invés da linha
de comando, consulte "sed & awk, 2nd Edition," por Dale Dougherty e
Arnold Robbins (O'Reilly, 1997; http://www.ora.com), "UNIX Text
Processing," por Dale Dougherty e Tim O'Reilly (Hayden Books, 1987)
ou os tutoriais do Mike Arst distribuídos como U-SEDIT2.ZIP (em vários
sites). Para explorar totalmente o poder do sed, deve-se entender
as "expressões regulares". Para isso, veja "Mastering Regular Expressions"
de Jeffrey Friedl (O'Reilly, 1997). As páginas de manual ("man pages")
dos sistemas Unix podem ser úteis (tente "man sed", "man regexp", ou
a subseção sobre expressões regulares no "man ed"), mas as páginas
de manual são notadamente mais difíceis de se compreender. Elas
não são escritas para ensinar o uso do sed ou das expressões 
regulares para usuários iniciantes, mas como texto de referência 
para aqueles que já tem certa experiência com as duas ferramentas.

SINTAXE DAS ASPAS: Os exemplos acima utilizam as aspas simples ('...')
ao invés das aspas duplas ("...") para agrupar comandos de edição,
visto que o sed é comumente utilizado em plataformas Unix. As
aspas simples impedem que a shell Unix interprete o cifrão ($)
e a crase (`...`), os quais seriam expandidos pela shell se estivessem
dentro das aspas duplas. Usuários da shell "csh" e derivadas
ainda precisarão utilizar a barra invertida (\) antes do sinal de 
exclamação (por exemplo \!) para conseguir rodar os exemplos acima, mesmo
usando as aspas simples. Versões do sed escritas para o DOS
invariavelmente necessitam das aspas duplas ("...") ao invés das
aspas simples para agrupar os comandos de edição.

USO DO '\t' NOS SCRIPTS SED: Para maior clareza na documentação, nós
utilizamos a expressão '\t' para indicar o caractere de tabulação 
(0x09) nos scripts sed. Porém, a maioria das versões do sed não reconhece
a abreviação '\t', logo, quando for executar estes scripts via linha
de comando, você deve apertar a tecla TAB. A abreviação '\t' só
é reconhecida como um metacaractere nas expressões regulares no
awk, perl, HHsed, sedmod, e o GNU sed v3.02.80.

VERSÕES DO SED: As versões do sed diferem entre si, logo, algumas 
variações na sintaxe são esperadas. Em particular, a maioria
não suporta o uso de rótulos (:nome) ou instruções ramificadas 
(b,t) na edição dos comandos, exceto no final dos mesmos. Nós utilizamos
uma sintaxe que seria portável para a maioria dos usuários do sed,
mesmo sabendo que a popular versão GNU do sed permite uma sintaxe
mais sucinta. Quando o leitor vê um comando comprido como esse:

   sed -e '/AAA/b' -e '/BBB/b' -e '/CCC/b' -e d

é importante que ele saiba que o GNU sed permite uma redução, como:

   sed '/AAA/b;/BBB/b;/CCC/b;d'		# ou mesmo
   sed '/AAA\|BBB\|CCC/b;d'

Lembre-se ainda que, apesar de muitas versões do sed aceitarem comandos
como "/one/ s/RE1/RE2/", algumas não permitem o uso de "/one/! s/RE1/RE2/",
a qual contém um espaço antes do 's'. Omita o espaço quando for digitar
o comando.

OTIMIZANDO PARA MAIOR VELOCIDADE: Se a velocidade de execução precisa
aumentar (em virtude de grandes arquivos de entrada ou de processadores
e discos rígidos lentos), a substituição será executada mais rapidamente
se a expressão de "procura" é especificada antes da instrução
"s/.../.../". Assim:

   sed 's/foo/bar/g' arquivo         # comando de substituição padrão
   sed '/foo/ s/foo/bar/g' arquivo   # executa de forma mais rápida
   sed '/foo/ s//bar/g' arquivo      # sintaxe mais sucinta

Na seleção ou remoção de linhas nas quais você somente precisa
ver uma primeira parte de um arquivo, o comando "quit" (q) no script
irá reduzir drasticamente o tempo de processamento para arquivos
grandes. Assim:

   sed -n '45,50p' arquivo           # imprime as linhas 45-50
   sed -n '51q;45,50p' arquivo       # mesma coisa, mas faz muito mais
                                     # rapidamente

Fonte: http://sed.sourceforge.net/sed1line.txt

Imagem docker lemp/lnmp de fácil uso

Eu uso docker para ambiente de desenvolvimento, logo não preciso de tamanha complexidade com várias imagens dependentes montagem de diretórios cruzados etc.

Para esta finalidade basicamente preciso de um servidor lemp (ou lnmp), que é sigla para “Linux, (e)nginx, mysql e php” e um php myadmin.

Assim sendo criei uma imagem disponível publicamente no docker hub para quem precisa desta finalidade.

Para subir a aplicação com esta imagem, basta criar um docker-composer.yml na raiz de seu projeto com o conteúdo abaixo:

web:
 image: fbraz3/lnmp
 volumes:
 - ./:/app/public/
 ports:
 - "127.0.0.1:80:80"
 - "127.0.0.1:3306:3306"

E depois rodar o comando:

docker-compose up -d

A aplicação estará acessível em http://localhost/ e o PHPMyAdmin em http://localhost/pma/ simples assim.

Já está pré-configurado e com todos os grants necessários uma base de dados com o nome de “app” (sem as aspas) para uso na aplicação.

Como uso essa imagem nos meus projetos venho sempre aprimorando ela, então o changelog vai ficar sempre disponível em https://hub.docker.com/r/fbraz3/lnmp/

 

Alguns comandos úteis em docker

Esse comando faz deploy de uma imagem e loga no bash dela

docker run -t -i -P --net=host image_name /bin/bash

Logar no ssh de um container

docker exec -i -t container_name bash

Docker-Compose: Subir imagem

docker-compose up -d

Docker-Compose: Descer imagem

docker-compose stop

Ao logar no ssh, alguns comandos que depoendem da variavel TERM podem apresentar comportamento anômalo (primcipalmente no editor VIM), é só executar esse comando:

export TERM=xterm

Otimizando o Linux com Swapiness

A partir das últimas versões do kernel 2.6.x, o kernel do linux passou a permitir que o usuário controle a partir de qual percentual de uso da memória RAM que será utilizado o swap.

Entretanto não se preocupe com essa questão de versão do kernel, pois atualmente o mesmo está na versão 4.x, então a não ser que você use um linux do tempo das cavernas sua distro terá suporte a esta configuração.

Existem duas maneiras de ver como seu swapiness está configurado:

sudo cat /proc/sys/vm/swappiness
60

ou

sysctl -a|grep swappiness
vm.swappiness = 60

no caso acima, ele irá utilizar swap a partir de 40% de uso da memória RAM (a configuração se baseia em memória disponível, então use sempre “100 – valor” para aplicar esta definição).

Primeiramente, poemos definir este valor em tempo de execução de forma testar qual valor melhor se adéqua a sua máquina

sysctl -w vm.swappiness=5

Acima configuramos para só usar o swap quando a memória RAM estiver 95% cheia (lembre do cálculo mencionado anteriormente).

O único problema é que essa configuração se perde ao reiniciar a máquina, então, para torná-la permanente, basta editar o arquivo /etc/sysctl.conf e adicionar/editar a seguinte linha:

vm.swappiness = 5

Certo, e qual número eu devo configurar?

A configuração vai depender da quantidade de RAM a máquina, mas por via e regra, quanto mais memória RAM, menor deverá ser o swapiness. 

Em um note com 4GB de RAM que uso pra desenvolvimento, consegui o melhor desempenho setando o número em 5, porém é interessante testar com outros valores antes e tornar a configuração definitiva 😉

criando proxy através do ssh

Eu uso muito esta técnica para efetuar testes em sistemas simulando acesso vindo de redes externas.

Esta dica funciona com qualquer servidor ssh que não possua bloqueios na porta 80 e 443. Logo também é possível o uso em servidores compartilhados!

Pra quem usa linux, é muit fácil, basta executar o comando abaixo no terminal e configurar o navegador para acesso a internet via proxy socks na porta determinada no comando

syntaxe:

ssh -Nn -D PORTA [email protected]

exemplo:

ssh -Nn -D 4050 [email protected]

No exemplo acima, basta configurar o navegador para acesso via proxy socks5 na porta 4050