Ir para o conteúdo
ou

Software livre Brasil

Tela cheia
 Feed RSS

Helio Loureiro

27 de Maio de 2009, 0:00 , por Software Livre Brasil - | Ninguém está seguindo este artigo ainda.

Fui detonado!

24 de Setembro de 2024, 10:22, por Home - helio.loureiro.eng.br - 0sem comentários ainda

facepalm

Um projeto engraçado no GitHub que serve pra te detonar baseado nos seus repositórios.  Estou rindo, mas é de nervoso.  É um tipo de Mauchine Learning.

Oh Helio Loureiro, trying to brew your own beer and code at the same time? I can only imagine the taste of your programming—bitter, flat, and with a hint of regret, just like your idea of collaborating on KDE while you’re still figuring out how to stop your Python scripts from crashing. With a profile that screams “I’m learning” louder than a Linux fanboy at a Windows convention, maybe it’s time to put down the homebrew and pick up a book on actual development skills. Your repos are like that friend who always says they’re "working on themselves" but never seems to get anywhere—76 repos and barely a pulse of interest. And by the way, do you really think the world needed another fork of SecLists? Your GitHub looks like a garage sale of uninteresting projects. But hey, at least you’re keeping Linux alive, one mediocre script at a time. Cheers to that!

O que se pode ler mais ou menos como:

Ah, Helio Loureiro, tentando fazer sua própria cerveja e programar ao mesmo tempo? Só consigo imaginar o gosto da sua programação — amargo, sem graça e com uma pitada de arrependimento, assim como sua ideia de colaborar no KDE enquanto você ainda está tentando descobrir como impedir que seus scripts Python travem. Com um perfil que grita "estou aprendendo" mais alto do que um fanboy do Linux em uma convenção do Windows, talvez seja hora de largar a fabricação caseira e pegar um livro sobre habilidades reais de desenvolvimento. Seus repositórios são como aquele amigo que sempre diz que está "trabalhando em si mesmo", mas nunca parece chegar a lugar nenhum — 76 repositórios e mal um pulso de interesse. E, a propósito, você realmente acha que o mundo precisava de outro fork do SecLists? Seu GitHub parece uma venda de garagem de projetos desinteressantes. Mas, ei, pelo menos você está mantendo o Linux vivo, um script medíocre de cada vez. Um brinde a isso!

Quem quiser experimentar a brincadeira, esse é o link:

https://github-roast.pages.dev/



Correndo atrás do tempo perdido com Go!

7 de Setembro de 2024, 13:19, por Home - helio.loureiro.eng.br - 0sem comentários ainda

RoadRunner 4 3371596983

Estou atualmente trabalhando numa empresa onde uma das visões da empresa é conseguir ter os dados do jogo finalizado disponível na interface de visualização em menos de 1 minuto.   Quase todo o código é escrito em typescript e uma pequena parte em rust.

Uma das partes mais pesadas é feita em shell, que é a parte de baixar e descompactar um arquivo da steam.  Pra ilustrar o que é feito, fiz esse script em shell que também serve como base de comparação de tempo.


#! /usr/bin/env bash
#

TARGET_URL="http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2"
DESTINATION="003705744548740202576_0842061407.dem.bz2"
UNPACKED="003705744548740202576_0842061407.dem"
CURLUNPACKED="curl-003705744548740202576_0842061407.dem"

die() {
  echo "ERROR: $@" &>2
}

rm -f $DESTINATION $UNPACKED $CURLUNPACKED

curl -o $DESTINATION \
  -L \
  $TARGET_URL ||
  die "Failed to download: $TARGET_URL"

bunzip2 $DESTINATION ||
  die "Failed to unzip $DESTINATION"

mv $UNPACKED $CURLUNPACKED

 O código então baixa esse link da steam e tem de descompactar o arquivo.  Qual é a velocidade dele?


helio@goosfraba ~/t/godownloader> time ./curl-downloader-2.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  216M  100  216M    0     0  60.3M      0  0:00:03  0:00:03 --:--:-- 60.4M

________________________________________________________
Executed in   29.61 secs    fish           external
   usr time   25.24 secs  585.00 micros   25.24 secs
   sys time    0.89 secs   71.00 micros    0.89 secs

 Podemos ver que o "curl" baixa o arquivo em mais ou menos 3 segundos, e gasta no total 25s, ou seja, uns 22s pra descompactar.  O total termina como 29s, mas vamos focar primeiramente no "usr time".

Então escrevi um código em Go pra tentar fazer isso de forma mais rápida.

package main

import (
        "compress/bzip2"
        "fmt"
        "io"
        "net/http"
        "os"
        "time"
)

const (
        TARGET_URL   = "http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2"
        DESTINATION  = "003705744548740202576_0842061407.dem.bz2"
        DECOMPRESSED = "go-003705744548740202576_0842061407.dem"
)

func main() {
        err := download(TARGET_URL, DESTINATION)
        if err != nil {
                panic(err)
        }

        err = bunzip2(DESTINATION, DECOMPRESSED)
        if err != nil {
                panic(err)
        }
}

func download(from, to string) error {
        fmt.Println("Downloading:", from)
        timeStart := time.Now()
        resp, err := http.Get(from)
        if err != nil {
                return err
        }

        defer resp.Body.Close()
        out, err := os.Create(to)
        if err != nil {
                return err
        }
        defer out.Close()

        _, err = io.Copy(out, resp.Body)
        if err != nil {
                return err
        }
        fmt.Println("Finished:", time.Since(timeStart).String())

        return nil
}

func bunzip2(from, to string) error {
        // https://gist.github.com/rickt/7817401
        fmt.Println("Unpacking:", from)
        timeStart := time.Now()
        pr, pw := io.Pipe()

        go func() {
                defer pw.Close()
                var inFile *os.File
                var err error
                inFile, err = os.Open(from)
                defer inFile.Close()
                if err != nil {
                        panic(err)
                }

                _, err = io.Copy(pw, inFile)
                if err != nil {
                        panic(err)
                }
        }()

        defer pr.Close()
        z := bzip2.NewReader(pr)
        var outFile *os.File
        var err error
        outFile, err = os.Create(to)
        defer outFile.Close()
        if err != nil {
                return err
        }

        _, err = io.Copy(outFile, z)
        if err != nil {
                return err
        }
        fmt.Println("Finished:", time.Since(timeStart).String())
        return nil
}

O código baixa o conteúdo num arquivo e depois descompacta.  Qual a velocidade?

helio@goosfraba ~/t/godownloader> go build -o go-downloader-2 main-2.go; time ./go-downloader-2 
Downloading: http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2
Finished: 3.536812275s
Unpacking: 003705744548740202576_0842061407.dem.bz2
Finished: 30.220663099s

________________________________________________________
Executed in   33.76 secs    fish           external
   usr time   29.90 secs    0.00 micros   29.90 secs
   sys time    0.95 secs  639.00 micros    0.95 secs

Muito lento.  Pior do que eu esperava.  Ele baixa o arquivo em 3.5s, mas leva 30s pra descompactar.  Um dos motivos é com certeza porquê eu salvo em arquivo e depois abro o arquivo pra descompactar.  Vamos então pra próxima versão onde eu passo io.Reader de um pro outro.

package main

import (
        "compress/bzip2"
        "fmt"
        "io"
        "net/http"
        "os"
        "time"
)

const (
        TARGET_URL   = "http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2"
        DESTINATION  = "003705744548740202576_0842061407.dem.bz2"
        DECOMPRESSED = "go-003705744548740202576_0842061407.dem"
)

func main() {
        data, err := readerDownload(TARGET_URL, DESTINATION)
        if err != nil {
                panic(err)
        }

        err = bunzip2Stream(data, DECOMPRESSED)
        if err != nil {
                panic(err)
        }
}

func readerDownload(from, to string) ([]byte, error) {
        fmt.Println("Downloading:", from)
        timeStart := time.Now()
        resp, err := http.Get(from)
        if err != nil {
                return nil, err
        }

        defer resp.Body.Close()
        content, err := io.ReadAll(resp.Body)
        if err != nil {
                panic(err)
        }
        fmt.Println("Finished:", time.Since(timeStart).String())
        return content, nil

}

func bunzip2Stream(from []byte, to string) error {
        // https://gist.github.com/rickt/7817401
        fmt.Println("Unpacking:", to)
        timeStart := time.Now()
        pr, pw := io.Pipe()

        go func() {
                defer pw.Close()

                //_, err := io.Copy(pw, from)
                pw.Write(from)
                //if err != nil {
                //              panic(err)
                //      }
        }()

        defer pr.Close()
        z := bzip2.NewReader(pr)
        var outFile *os.File
        var err error
        outFile, err = os.Create(to)
        defer outFile.Close()
        if err != nil {
                return err
        }

        _, err = io.Copy(outFile, z)
        if err != nil {
                return err
        }
        fmt.Println("Finished:", time.Since(timeStart).String())
        return nil
}

Qual o desempenho?

helio@goosfraba ~/t/godownloader> go build -o go-downloader-3 main-3.go; time ./go-downloader-3
Downloading: http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2
Finished: 3.624793323s
Unpacking: go-003705744548740202576_0842061407.dem
Finished: 29.883794408s

________________________________________________________
Executed in   33.52 secs    fish           external
   usr time   30.03 secs  580.00 micros   30.03 secs
   sys time    0.96 secs   69.00 micros    0.96 secs

Melhorou mas ainda estou longe de fazer melhor que a versão em shell script.  O tempo de descompactar baixou irrisóriamente 1s.  Mesmo não tendo SSD ou NVME meu disco é rápido o suficiente pra isso não impactar ao todo.

Comecei a pesquisar como poderia melhorar o desempanho do pacote bzip2 do Go! e existe uma discussão sobre isso em aberto.

https://github.com/golang/go/issues/6754

A reclamação é sobre versões mais antigas de Go! e até Robert Pike opinia.  Acho que melhorou bastante pros dias de hoje, mas continua lento se comparado com o binário do programa.  O que fazer então?  Declarar derrota?

Talvez.  Mas ao invés disso eu passei a procurar outras libs no GitHub.  E encontrei o uso do pbzip2, que diz ser mais rápido queo bzip2 do standard.  Então vamos ao código:

package main

import (
        "context"
        "fmt"
        "io"
        "net/http"
        "os"
        "time"

        "github.com/cosnicolaou/pbzip2"
)

const (
        TARGET_URL   = "http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2"
        DESTINATION  = "003705744548740202576_0842061407.dem.bz2"
        DECOMPRESSED = "go-003705744548740202576_0842061407.dem"
)

func main() {
        data, err := readerDownload(TARGET_URL, DESTINATION)
        if err != nil {
                panic(err)
        }

        err = pbunzip2Stream(data, DECOMPRESSED)
        if err != nil {
                panic(err)
        }
}

func readerDownload(from, to string) ([]byte, error) {
        fmt.Println("Downloading:", from)
        timeStart := time.Now()
        resp, err := http.Get(from)
        if err != nil {
                return nil, err
        }

        defer resp.Body.Close()
        content, err := io.ReadAll(resp.Body)
        if err != nil {
                panic(err)
        }
        fmt.Println("Finished:", time.Since(timeStart).String())
        return content, nil

}

func pbunzip2Stream(from []byte, to string) error {
        // https://gist.github.com/rickt/7817401
        fmt.Println("Unpacking:", to)
        timeStart := time.Now()
        pr, pw := io.Pipe()

        go func() {
                defer pw.Close()

                //_, err := io.Copy(pw, from)
                pw.Write(from)
                //if err != nil {
                //              panic(err)
                //      }
        }()

        defer pr.Close()
        ctx := context.Background()
        z := pbzip2.NewReader(ctx, pr)
        var outFile *os.File
        var err error
        outFile, err = os.Create(to)
        defer outFile.Close()
        if err != nil {
                return err
        }

        _, err = io.Copy(outFile, z)
        if err != nil {
                return err
        }
        fmt.Println("Finished:", time.Since(timeStart).String())
        return nil
}

E finalmente, a medida de desempenho:

helio@goosfraba ~/t/godownloader> go build -o go-downloader-4 main-4.go; time ./go-downloader-4
Downloading: http://replay272.valve.net/730/003705744548740202576_0842061407.dem.bz2
Finished: 3.74774932s
Unpacking: go-003705744548740202576_0842061407.dem
Finished: 6.108665607s

________________________________________________________
Executed in    9.89 secs    fish           external
   usr time   44.22 secs    0.00 micros   44.22 secs
   sys time    0.78 secs  655.00 micros    0.78 secs

Vitória!  O pbzip2 que faz a descompressão em blocos em paralelo levou 6s.  Isso sim é performance.  O "usr time" mostra 44s por algum motivo bizarro, mas o tempo total foi por volta de 10s.  E o resultado?

helio@goosfraba ~/t/godownloader> sha256sum curl-003705744548740202576_0842061407.dem \
go-003705744548740202576_0842061407.dem eca9bdd943521251b8704397e40b7f9aada539698561a6c1aca58ebf2602bfc1 curl-003705744548740202576_0842061407.dem eca9bdd943521251b8704397e40b7f9aada539698561a6c1aca58ebf2602bfc1 go-003705744548740202576_0842061407.dem

Então foi baixado e descompactado bem mais rápido e sem corromper os dados.

Um ponto a ser visto é que talvez exista também um binário pronto com pbzip2 pra descompactar.  E pode ser que seja mais rápido que em Go!  Mas é pra isso que servem os desafios.  Por enquanto vou celebrar minha pequena vitória com uma cerveja.

victory



Ferramentas modernas de Unix

6 de Setembro de 2024, 16:38, por Home - helio.loureiro.eng.br - 0sem comentários ainda

modern unix livros 

Quando comecei a aprender Linux e Unix, no século passado, esses dois livros eram meus referenciais sobre ferramentas pra usar.  Unix Power Tools e Unix System Administration Handbook.  Foram e continuam excelentes livros, mas as ferramentas passaram a ser muito melhores.  A grande maioria re-escrita em rust ou em Go! pra maior velocidade e até mesmo segurança.

Eu usava uma ferramenta aqui e outra ali até ler um artigo sobre o assunto e depois achar uma boa referência no GitHub.  O artigo que li no começo eu já não lembro e não tenho o link, mas as ferramentas eu fui pegando por essa referência aqui:

https://github.com/ibraheemdev/modern-unix

Então vou listar as ferramentas que uso atualmente.  Pegue a pipoca e sente bem confortavelmente que são várias.  Não existe ordem de preferência e eu geralmente não adoto duas ferramentas pra mesma coisa.  Mostro aqui o que é de uso no dia à dia de trabalho.

Eu estou colocando o link pra cada uma na imagem, mas a grande maioria funciona pelo sistema de pacotes das distros.  Dê uma olhada nisso antes de baixar do site.

Fish shell

modern unix fishshell

Eu sinta uma pena muito grande de ver quem fica preso ao bash nos dias de hoje.  Não me entenda mal se você é uma dessas pessoas: bash é excelente.  Mas existem alternativas muito superiores.  Uma delas é o fish.  Eu ouvi falar pela primeira vez do fish através do Kov na mesa do Debian numa das edições do FISL.  E confesso que achei... aquilo não era pra mim. Eu estava confortável no meu bash.   Eu não poderia estar mais enganado.

Na segunda tentativa, eu me forcei a usar o fish por no mínimo 6 meses.  E o que aconteceu?  Não consigo mais ficar sem ele.  É o meu shell de linha de comando em todo lugar.  Eu ainda uso o bash pra scripts, mas pra linha de comando, fish shell.

Starship

modern unix starship

Esse eu conheci mais recentemente por uma dica do Mastodon.  Eu sinceramente não lembro quem recomendou, mas lembro de bastante gente elogiando.  Testei e gostei.  É um formatador de prompt.  Ao invés de ficar configurando temas no shell, é só botar o starship pra carregar no login e tá pronto.

Bat

modern unix bat

O bat é um substituto bem legal ao cat.  É mais lento que o cat, mas traz ferramentas visuais com cores que facilitam olhar um arquivo. Isso te faz achar que a pequena lentidão pra ler o resultado vale o esforço, ou tempo.

Nota: por alguma motivo bizarro, no Ubuntu o binário instalado é batcat.  Eu geralmente faço um link simbólico pra apenas bat.

Htop

modern unix htop

Esse é um excelente substituto ao "top".  Bem mais gráfico e colorido.  Eu nem considero algo tão moderno assim porque uso já faz mais de 10 anos.  Mas recentemente descobri que tem gente que não sabe de sua existência.  Então fica aqui na lista registrado.

Duf

modern unix duf

Um programa que subtitui o "df" pra ver o tamanho e uso de partições.

Dust

modern unix dust

Usa o "du" pra ver qual o tamanho de arquivos e/o ou diretórios?  Pois chegou sua evolução.

Exa/Eza

modern unix exa

Esses são substitutos ao "ls".  A sintaxe não é 100% compatível.  Por exemplo "-tr" não funciona neles, mas você pode usar algo mais simples como "--sort=created".  O programa começou como exa, que tem disponível no Ubuntu 24.04, mas no Archlinux passaram pra eza.  Imagino que foi um fork porque o primeiro deve ter parado o desenvolvimento.

Procs

modern unix procs

Ainda usa "ps" pra listar processos?  E fica bolado que quando manda um "grep", o mesmo aparece na listagem?  Pois o procs resolve esse problema.

Ripgrep

modern unix ripgrep

O ripgrep, que apesar do nome tem como binário apenas "rg", é um excelente substituto do grep pra procurar em arquivos de determinado diretório.  Ou diretórios.  E bem mais rápido.

Glances

modern unix glances summary

O glances é escrito em python.  Legal, mas isso o torna lento pra iniciar.  Mas depois que inicia, funciona bem.  Ele é um melhoramento do "htop" com mais informação.

Jq

modern unix jq

Se você mexe com kubernetes ou com arquivos json, jq é a ferramenta.  Ajuda a filtrar e dá o resultado num formato colorido, o que ajuda a visualizar.  E você pode construir filtros pros resultados.  Existe uma outra ferramenta que é mais rápida, mas eu acabo usando o jq por causa da saída colorida (que ajuda demais).

Tldr

modern unix tldr

Sabe aquele problema de ler manpage e não ter exemplos?  O tldr resolve essa parte.  Baixa exemplos do comando que quiser usar. 

Fd

modern unix fd 

No Ubuntu o pacote chama-se fd-find.  E instala o binário como fdfind.  Eu renomeio pra fd, tal qual é no archlinux e no macOS.  É um melhoramento do find.  Mais rápido e mais fácil de usar.

McFly

modern unix mcfly

Esse entra aqui como uma menção quase que honrosa porque atualmente eu já não uso mais.  Ele é prático se você usar outro shell que não seja o fish, como bash ou zsh.  Ele faz a busca no histórico ser de  uma forma bem mais simples.  Tal como já é por padrão no fish.

Zsh

modern unix zsh

A imagem é do oh-my-zsh, que deixa o terminal mais bonitinho.  O zsh mesmo não tem imagem na página do projeto.  Se é que é um projeto.

O zsh é o padrão no macOS e eu resolvi experimentar por 6 meses na máquina que peguei no refresh da Ericsson.  A vantagem do zsh é que é a mesma sintaxe do bash, então você reaproveita muita coisa.  Agora sobre trocar zsh por bash... no final eu achei bem parecido.  Existem algumas vantagens do zsh, mas no uso do dia à dia, pra mim pelo menos, não fez tanta diferença assim.

Update

O Patola lembrou bem que existem comportamentos distintos entre bash e zsh.

Em bash:

patola@risadinha:/dados$ echo a | read b ; echo $b
patola@risadinha:/dados$

Em zsh:

[19:03] [9665] [patola@risadinha /dados]% echo a | read b ; echo $b
a
[19:03] [9666] [patola@risadinha /dados]%

O resultado é diferente porque a sintaxe é diferente. O bash tem right-side fork, o zsh tem left-side fork. Isso não é controverso. É uma diferença de sintaxe conhecida, explicada e verificável.
        -- Patola

K9s

modern unix k9s 

Essa não é bem uma dica pra quem mexe com kubernetes.  Ao invés de ficar mandando "kubectl" pra tudo quanto é lado, o melhor é usar o k9s.  Ele mostra de forma visual o seu cluster e namespace.  E todos os atributos que consegue ver pelo "kubectl".

E acabamos aqui...

E assim terminamos o artigo.  Se eu lembrar de mais alguma coisa que uso e esqueci, acrescento aqui.

 

 



Nem tudo é o que parece...

28 de Agosto de 2024, 21:50, por Home - helio.loureiro.eng.br - 0sem comentários ainda

Em minha empolgação com o brinquedo novo, o Lenovo Thinkpad T480, eu simplesmente não percebi que várias teclas são adesivos colados.

Fui mirim.



Vai mudar... mudou!

28 de Agosto de 2024, 21:44, por Home - helio.loureiro.eng.br - 0sem comentários ainda

Pode não parecer, mas mudamos. Já estamos na VPS nova, que fica na Hetzner.

Está no datacenter que fica na Finlândia. Então é quase vizinho daqui.

Espero não levar nenhum susto no fim do mês ao pagar o uso. Por enquanto parece tudo ok.

Sem mais, seguimos em frente.



Tags deste artigo: #debian #debianbr #debianse #softwarelivre #freesoftware #linux #python