Com o spoiler to título, já sabem que não tive COVID. Mas fiquei doente, bastante, e vou contar como funcionou o sistema de saúde sueco.
Tudo começou numa segunda-feira (tinha de ser coisa de segunda-feira mesmo), ao fim do dia. Comecei a sentir aquela típica dor nas costas e calafrios de febre. Não deu outra: 39°C de febre dali uma meia hora. Como eu já tinha tido uma virose um tempo atrás, já sabia que o procedimento era aguardar pelos menos 2 dias antes de entrar em contato com o sistema de saúde.
Passado os 2 dias, nada da febre baixar, então procurei o sistema de saúde. Se é uma emergência, o número é 112. Do contrário, o número é o 1177. É possível acessar o sistema de saúde por web também, através do https://1177.se, mas eu preferi por telefone. Ao ser atendido, uma das opções é pra continuar em inglês. Sei que existem suportes a outras línguas como árabe e eritréia (na verdade não sei como chamam a língua da Eritréia em português, que fica Eritrean em inglês). Fiquei uns 2 minutos na espera até que alguém atendeu a ligação. Conversamos sobre os sintomas e a pessoa disse que realmente poderia ser COVID. Então eu teria de estar isolado em casa, o que já tinha feito desde o primeiro dia, e pedir o teste pra confirmar. Pra eu não ter de decifrar como pedir o teste, foi enviado um SMS com o link direto pra eu fazer o pedido. E fiz.
Eu tinha ligado no terceiro dia de manhã, mas o teste só foi entregue no dia seguinte, pois a fila de gente pedindo era grande. Foi entregue em casa por um motorista de táxi. Ele me telefonou antes de chegar avisando que estava a caminho.
O kit de teste era esse aqui:
Nada de muito sofisticado. Um cotone, um prato descartável, uma cápsula pra conter o cotonete e saquinhos plásticos pra fechar tudo. Minhas informações estava no QR-code borrado. Veio tudo em sueco mas...
instruções em inglês no site.
Fiz a coleta, ligue de novo pro motorista e deixei a amostra do lado de fora da porta.
Nesse meio tempo segui apenas a recomendação que passaram: tomar algum remédio pra baixar a febre e não ficar o tempo todo na cama. Doses de paracetamol deram conta do recado.
No mesmo dia em que fiz o exame eu já recebi o resultado. Era umas 10 ou 11 horas da noite, mas veio por SMS. Teste negativo.
Foi um grande alívio, mas mesmo assim passei 5 dias com febre. Liguei no 1177 no dia seguinte e eles disseram que poderia mesmo ser uma gripe. Mas em caso da febre continuar persistindo eu deveria buscar o posto de saúde próximo de casa pra buscar ajuda. Não precisei.
Não houve nenhuma recomendação ou sugestão pra usar coisas como cloroquina ou ivermectina, remédios que fazem a cabeça dos brasileiros. Apenas algo pra manter a febre baixa. E beber bastante água.
Talvez no próximo post eu explique um pouco como funciona o sistema de postos de saúde aqui.
Esse é um artigo meio que requentado. Eu o preparei no ano passado pra uma edição da Revista do Espírito Livre sobre a pandemia que no fim nunca foi lançada. O que descrevo é um retrato de como estava a situação da Suécia na época. Estamos em 2021 e muita coisa mudou. E pra pior. Mas isso eu deixo pra comentar mais pra frente em outro artigo.
---
Não acompanho muito de perto como está a pandemia no Brasil. Mas vejo pelas notícias que chegam por aqui que está uma bagunça geral e que em certos pontos citam a Suécia como referência. E não só no Brasil: nos EUA também vejo muitas pessoas citando a Suécia como exemplo, no início como bom, e ultimamente como mau.
Eu já vivo no coração da escandinávia, em Estocolmo na Suécia, mais de 5 anos e vou descrever um pouco de como foi e está sendo enfrentada a pandemia por aqui, como as coisas mudaram, como tudo foi afetado. Vou aproveitar o parágrafo pra pedir desculpas pelos ângulos das fotos. Todas foram tiradas de uma câmera gopro que uso em meu capacete quando estou andando de bicicleta. E como é um bicicleta road, o ângulo sai um pouco pra baixo.
A Suécia não decide sua política pública de saúde por meio de ministros ou governo. Existe uma autoridade de saúde que publica os fundamentos das políticas a serem adotadas e todos seguem. O governo poderia ir contra o que é recomendado mas essa autoridade é composta por epidemiologistas especialistas. A cara do órgão é Anders Tegnell, epidemiologista reputadíssimo que chefiou inclusive equipes na luta contra ebola. É ele quem geralmente aparece no relatório diário que é feito sobre a evolução da epidemia. Não somente ele, mas a equipe que trabalha lá decide quais são as medidas adotadas por aqui.
Mas nem tudo são flores. Muitos outros cientistas, também renomados, são contra as medidas adotadas aqui. E chegaram mesmo a fazer uma carta pública contra Tegnell. Mas aparentemente aqui a ciência fala mais alto e ele continua sendo o chefe por lá.
Entre as decisões tomadas pra conter o avanço da doença, foram decretadas as seguintes medidas: distanciamento social, creches e escolas primárias abertas, restaurantes e bares só atendem clientes sentados em mesas e existem espaçamentos de 1 mesa entre cada mesa, que trabalhem de casa os que puderem, completo isolamento de asilos, e permitidos agrupamentos com menos de 50 pessoas.
Essas medidas parecem simples e fogem do padrão de lockdown que muitos outros fizeram como solução, como foram os casos da Espanha e da Itália. O argumento aqui foi que não existe nenhum estudo comprovando a eficácia do isolamento, que uma vez tendo as pessoas novamente em circulação, o vírus espalhará como faria normalmente e que as pessoas não são estúpidas. Todos entendem que há uma pandemia lá fora.
Isso resultou em ruas vazias. Muitos pequenos negócios estão falindo, inclusive restaurantes e bares que podem ficar abertos. As ruas costumam ficar desertas. O empreendedor que dirigia táxi ou uber está praticamente sem trabalho. Serviços como cabeleireiros estão vazios. Lojas estão às moscas. Não declarar lockdown não foi o que salvou o comércio aqui. Pra amenizar os efeitos econômicos da pandemia, o governo editou uma série de pacotes de ajuda, como pagar 40% do salário de quem teve o número de horas trabalhadas reduzidas, sendo a empresa arcando com 50% e os 10% restantes seriam por conta do trabalhador. E até mesmo o pagamento de financiamento de casa pode ser suspenso por mais de 1 ano.
Mesma rua, um pouco à frente da foto anterior. Algumas pessoas nas mesas de fora, o que dá a sensação de estar cheio, mas são apenas essas pessoas. Dentro o bar estava vazio.
Como não estamos em lockdown o governo recomenda que todos saiam de casa pra fazer exercícios e aproveitar o sol, que é uma coisa rara na Suécia e costuma sumir por longos 4 meses de pesado inverno. O ponto que levam em questão é que para saúde mental é importante as pessoas manterem hábitos saudáveis como andar pelos parques, andar de bicicleta ou correr. E muita gente segue essa recomendação por aqui, inclusive eu.
E quem olhar bem atentamente pras fotos vai perceber que não há quase ninguém usando máscaras. Esse é outro ponto controverso, mas a autoridade de saúde diz que não há comprovação da eficácia do uso de máscaras contra o COVID-19. Por favor não enviem mails ou mensagens me xingando ou links pra artigos que dizem o contrário. Eu não sou a autoridade sueca, que conta com médicos especialistas em doenças infecciosas. Mas em geral é o que acontece quando comento esse item.
Qual o resultado pra essa política? Até agora o número de mortos é muito acima dos outros países nórdicos, mas todos implementaram lockdown. Esse é o grande drama do modelo sueco: as pessoas não estão enclausuradas em casa, mas isso fez com que o número de mortos fosse grande. Um dos maiores do mundo (estamos chegando ao número de 5 mil mortos com o número de mortos por dia caindo). O argumento é que não faltaram leitos em UTI pra essas pessoas, o que é verdade. Houve preparo com até hospital de campanha sendo criado em 2 semanas, e que foi desmontado recentemente por falta de uso. No pico da contaminação da doença o número de leitos utilizados foi por volta de 500 dos 1500 disponíveis. Atualmente esse número é abaixo de 400. A taxa de mortalidade do vírus é muito alta em idosos, que foi onde a Suécia admite que errou: deveria ter bloqueado acesso aos idosos desde o início. E treinado melhor os funcionários de asilos, pois há relatos de que muitos foram trabalhar sem equipamentos de proteção adequados e mesmo alguns com sintomas de gripe.
Outro ponto que as estatísticas mostraram foi que os mais afetados em sua maioria eram idosos de famílias de imigrantes. A teoria é de que ao contrário dos suecos, existem pessoas de diferentes idades vivendo na mesma residência e isso permitiu o espalhamento da doença mais facilmente entre esses avôs e avós que viviam com os netos na mesma residência. Nesse ponto traçam um certo paralelo com o que aconteceu na Itália, onde dizem ser algo parecido em termos de moradia.
Ao contrário dessas famílias, o povo nórdico gosta de viver sozinho. O índice de pessoas que vivem só é algo em torno de 56% da população. Bom… não posso nem reclamar pois sou praticamente parte dessa estatística.
Escrevi bastante sobre o corona vírus e como a sociedade nórdica tem enfrentado o mesmo, mas não escrevi nada sobre software livre. Dos eventos que eu em geral participava, todos viraram online ou serão online. Das atividades que teríamos, como hackathons, todas ou foram online ou foram canceladas. Eu sou do board de organização da PyCon Sweden e esse ano já definimos que será online, e copiado como foi feita com a bela experiência da conferência Pyjamas, criado no Brasil. Mesmo que por milagre a doença amenize, ninguém acredita que as todos se sentirão seguros em estar em um aglomerado com 200 a 500 pessoas juntas. Não esse ano. E talvez nunca mais.
Como nossa organização sempre foi online, pouca coisa mudou. Mantemos nossas reuniões bi-semanais por conferência via browser e salvamos as minutas no github. Usamos o telegram pra conversas rápidas e mesmo manter os interessados na conferência a par do que está sendo feito.
E seguimos em frente.
Então acho que era isso que eu tinha pra descrever sobre como estamos enfrentando a pandemia aqui na Suécia. A receita parece simples, mas por aqui as coisas são levadas à sério. Então se quiserem seguir o exemplo sueco minha dicas são: fiquem em casa o máximo que puderem, ao sair de casa mantenham a distância de 2 metros ou mais uns dos outros, caso isso seja difícil usem máscaras, e lavem bem as mãos e com bastante frequência.
Hélio Loureiro
No Brasil muita gente já está preparando pra pular carnaval, mesmo com pandemia, e eu aqui aparecendo só agora com uma análise de 2020. Era pra ter feito lá pro fim ou começo do ano? Com certeza. Mas quem sou eu pra conseguir manter um ritmo desses?
Então vamos ver os dados.
Esse foi o tráfego anual. Nada de muita novidade. Média de 10 pessoas acessando por dia. Algum repique em maio (o que fiz em maio?) mas nada assombroso. Quase 3/4 do tráfego vindo de... busca orgânica? Quase 20% de links diretos (imagino que posts no twitter e no telegram). É... não foi um ano muito bom em tráfego mas a culpa é toda minha. Fui bem negligente quanto ao conteúdo. Acho que postei 4 ou 5 artigos só durante 2020.
Dos países que acessaram, Brasil ganha de longe. Ainda bem pois o conteúdo é em geral na língua tupiniquim. Mas interessante ver outros países com China e França na métrica, mesmo que tenham sido só uns 20 acessos cada.
Esses são os links mais acessados. A página orgânica é a frente do site. Interessante ver o interesse no artigo sobre o final da Linux Mall, que deixou muitas saudades. E... telnet via script? não achei que isso tivesse tanto interesse.
Maioria dos acessos vindo de desktops, com uma pequena parcela vindo de telefone. E alguns bem perdidos com tablet. Então toda a gritaria de avisos que o google manda sobre site não adaptado pra dispositivos móveis eu posso solenemente ignorar. Longa vida aos desktops!
E na guerra dos navegadores, Chrome nadando de braçadas. Firefox atrás mas muito atrás. Ao menos não vejo mais as estatísticas com vários acessos de Internet Explorer, se bem que ainda apareceram 19.
Em termos de sistemas operacionais... é... algumas coisas não mudam. Maioria dos acessos por Windows. Triste estatística. Interessante que tive 1 acesso de 1 Tizen.
E a linguagem do navegador? Maioria de brasileiros. Interessante notar Tchéccia (nem sei como escreve em português, mas é a antiga República Tcheca).
E é isso. Não um posto longo, mas apenas pra guardar de lembrança e comparar com o próximo em 2022.
Por muitos anos o meu comando preferido pra baixar páginas e até fazer mirrors foi o comando wget. Até eu descobrir o curl.
Não que eu já não conhecesse o curl. Com tantos anos de estrada com Unix, principalmente Linux e FreeBSD, curl era um conhecido que eu evitava usar. O motivo? Zona de conforto. wget era um comando conhecido e que eu sempre usava, desde que ando comecei a aprender Unix, em 1997. curl por outro lado era talvez tão antigo quanto, mas cheio de opções cabulosas que eu sentia um certo receio de usar.
Atualmente eu trabalho bastante com backend web e curl virou meu braço direito. E conforme fui aprendendo a usar mais, fui adorando. Hoje em dia não faço um container que seja sem o curl dentro. E acabei até deixando pra lá o wget mas... hoje é dia de falar de curl.
Durante essa semana no trabalho tivemos um problema de servidor web down. Ao tentar conectar ele ficava um tempo tentando dar a resposta e depois enviava um erro 500 (acho que era 503, mas isso não importa). Então como eu queria acessar o serviço assim qeu estivesse disponível e não queria ficar dando reload na aba do navegador, fiz um script com curl. Ele usa uma das opções do curl de retorna um valor do header de resposta, que no caso era os status code.
status_code=0
while [ $status_code -ne 200 ]
do
sleep 10
status_code=$(curl -s -o /dev/null -w "%{http_code}" https://helio.loureiro.eng.br/)
echo "status_code=$status_code"
done
O script fica monitorando o site e retorna o valor do status code em loop.
status_code=500 status_code=500 status_code=500 status_code=500 status_code=500 status_code=200
Assim que receber uma resposta 200, que é ok, para. Deixei isso rodando num shell no canto do desktop (uso duas telas então não bloqueou minha visão de nada). Assim que parou, voltei ao browser e acessei o serviço.
Coisa linda, não?
Se você tentou usar o pip, o gerenciador de módulos do python, nos últimos tempos então deve ter dado de cara com o seguinte erro:
/tmp > pip search conda ERROR: Exception: Traceback (most recent call last): File "/usr/local/lib/python3.6/dist-packages/pip/_internal/cli/base_command.py", line 224, in _main status = self.run(options, args) File "/usr/local/lib/python3.6/dist-packages/pip/_internal/commands/search.py", line 62, in run pypi_hits = self.search(query, options) File "/usr/local/lib/python3.6/dist-packages/pip/_internal/commands/search.py", line 82, in search hits = pypi.search({'name': query, 'summary': query}, 'or') File "/usr/lib/python3.6/xmlrpc/client.py", line 1112, in __call__ return self.__send(self.__name, args) File "/usr/lib/python3.6/xmlrpc/client.py", line 1452, in __request verbose=self.__verbose File "/usr/local/lib/python3.6/dist-packages/pip/_internal/network/xmlrpc.py", line 46, in request return self.parse_response(response.raw) File "/usr/lib/python3.6/xmlrpc/client.py", line 1342, in parse_response return u.close() File "/usr/lib/python3.6/xmlrpc/client.py", line 656, in close raise Fault(**self._stack[0]) xmlrpc.client.Fault: <Fault -32500: "RuntimeError: PyPI's XMLRPC API has been temporarily disabled due to unmanageable load and will be deprecated in the near future. See https://status.python.org/ for more information.">
Olhando no link apontado pelo erro, temos uma bela mensagem de erro.
As mensagens no site são as seguintes:
Traduzindo em miúdos: o site não está aguentando o tráfego. Simples assim.
Não vou entrar no mérito de como o site foi feito, se com flash, django, ou o que quer que seja que esse não é o ponto. O ponto é que fizeram uma péssima arquitetura. Um único ponto de controle que não sustenta o tráfego.
Quantos anos existe o Debian Mais de 25 já. O Debian criou uma solução pra isso já faz mais de uma década: repositórios com mirrors e pacotes assinados. Ao rodar o comando apt ou apt-get, uma listagem dos arquivos disponíveis é verificada. Se a informação do arquivo for a mesma do arquivo local, não é baixado. Isso diminui em muito a carga em cima dos servidores.
Já os pacotes pip usam um formato xml que provavelmente é baixado toda vez. Não só isso: não existe um pip stable, unstable e testing. A cada nova pequena versão do pacote, um novo arquivo é gerado. Isso torna cache dessa list impossível de ser mantido por qualquer mirror. E é o mesmo problema que se encontra em npm, compose, etc.
O contraponto de ter esse arquivo sempre atualizado é ter as versões mais recentes dos pacotes, módulos ou classes que se esteja usando. Mas o custo é alto em termos de capacidade de rede pra aguentar esse tráfego. O resultado é esse que vemos com o pip.
Terá solução? Acredito que sim. Mas sem re-pensar na arquitetura do pip, como receber módulos novos e atualizações, vai ser apenas como enxugar gelo.
Não sei já descrevi isso aqui ao longo desses 20 anos de blog/site, mas a maioria das coisas que publico são pra mim mesmo. Como tenho certeza que não vou lembrar o que fiz daqui algum tempo (provavelmente dias), eu deixo aqui registrado como bloco de notas pra referência. E, claro, espero que isso também ajude mais pessoas além de mim.
Como moro fora do Brasil já faz algum tempo, e ainda não domino a língua (na verdade só apanho dela), eu preciso de tempos em tempos pegar documentos e ler. A forma que encontrei é passar o documento em um scanner, se for papel, mas ter a certeza de ter o documento digitalizado em formato PDF no final. Esse foi o formato que mais facilitou o uso de outro software pra OCR (Optical Character Recognition), ou reconhecimento ótico de caracter.
Também percebi que o melhor é ter o documento separado em vários PDFs se possível, um pra cada página. Isso facilita pro software de OCR de reconhecer cada página corretamente.
Pra usar como exemplo aqui vou adotar um documento sobre o imposto de renda sueco. Ele está disponível na página do que seria equivalente à receita federa: https://www.skatteverket.se
O documento será esse aqui: https://www.skatteverket.se/download/18.7eada0316ed67d7282aedd/1582550479006/dags-att-deklarera-skv325-utgava41.pdf
Pra começar, apenas baixar o documento usando o curl:
curl -o report.pdf https://www.skatteverket.se/download/18.7eada0316ed67d7282aedd/1582550479006/dags-att-deklarera-skv325-utgava41.pdf
Em seguida serão necessários os seguintes pacotes de software (assumindo um sistema ubuntu ou debian): curl, ghostscript, imagemagick, tesseract-ocr e tesseract-<língua>. Como no caso eu pego os documentos em sueco, uso então tesseract-swe.
sudo apt install curl ghostscript imagemagic tesseract-ocr tesseract-swe
O arquivo então será baixado e salvo como "report.pdf". Ao abrir o documento eu vejo quantas páginas são, o que poderia ser feito de alguma outra forma mais automática, mas a visualização assim é fácil até pra detectar logo se tem alguma página pra pular com imagens. Esse documento tem 8 páginas.
Então pra separar o arquivo em PDF baixado em páginas separadas, que depois vai facilitar o trabalho de tradução, eu uso o seguinte comando:
for i in $(seq 1 8)
do
gs -sDEVICE=pdfwrite -q -dNOPAUSE -dBATCH -sOutputFile=report-$i.pdf -dFirstPage=$i -dLastPage=$i report.pdf
done
Com as páginas criadas separadamente em formato PDF e com os nomes como report-1.pdf, report-2.pdf, report-3.pdf, etc e o próximo passo é converter cada uma no formato TIFF, que é o formato onde o reconhecimento de caracteres funciona melhor. O programa "convert" que faz isso é parte do pacote imagemagick
for i in $(seq 1 8)
do
convert report-$i.pdf report-$i.tiff
done
Isso gera então as sequências report-1.tiff, report-2.tiff, etc.
Agora finalmente o passo final pra ter os textos em plain text.
for i in (seq 1 8)
do
tesseract report-$i.tiff report-$i -l swe
done
E isso cria os documentos com extensão "txt". Esse documento que escolhi não foi muito feliz na detecção de caracteres. O arquivo que mais foi reproduzido de forma satisfatória foi a página 7:
helio@xps13ubuntu:exemplo$ cat report-7.txt
Har du skatt att betala på din
preliminära skatteuträkning?
Tabellen på sidan 6 visar när skatten senast ska vara
betald. Fram till dess kan du göra delbetalningar.
Du kan när som helst betala in pengar till ditt
skattekonto. Du kan betala antingen med Swish
BIS
Om duvill betala med Swish loggar du in på Mina
sidor och följer instruktionerna där, Du kan också
enkelt betala din kvarskatt med Swish i samband
med att du deklarerar med edegitimation i
tjänsten. Du kan betala skatt med maximalt
15.000 kronor per dygn med Swish.
Om du betalar genom att göra en inbetalning till
BARR Sr ehe
angeditt OCR-nummer som du hittar i din preli-
PST RR NAS TT NT
www.skatteverketse/ocr.
Läs mer på wwwskotteverket.se/betalokvarskatt.
O passo seguinte é copiar essas páginas e colocar no google translator. Eu não automatizo esse passo e uso o simple copy&paste no browser.
E esse seria o resultado do trecho acima:
Você tem imposto a pagar sobre o seu cálculo preliminar do imposto? A tabela na página 6 mostra quando o imposto deve durar pago. Até então, você pode parcelar. Você pode depositar dinheiro no seu a qualquer momento conta fiscal. Você pode pagar com Swish BIS Se você quiser pagar com Swish, faça login no Mina páginas e siga as instruções lá, você também pode pague facilmente seu imposto residual com o Swish em conjunto com isso você declara com edegitimação em o serviço. Você pode pagar impostos com um máximo SEK 15.000 por dia com Swish. Se você pagar fazendo outro pagamento BARR Sr ehe número OCR especificado que você encontra na sua PST RR NAS TT NT www.skatteverketse / ocr. Leia mais em wwwskotteverket.se/betalokvarskatt.
Parem as prensas!
Estava aqui dando uma olhada em artigos do site, num bug de data do Joomla, quando achei o artigo 10 anos de Loureiro.Eng.BR que achei bonitinho. E fui ler.
CARACA! Eu perdi a data de 20 anos. Já são 20 anos e 7 meses de Loureiro.Eng.BR no ar. 20 anos!!!!
Nessa zique-zira de pandemia a data passou batida, mas sim, 20 anos no ar.
Não tenho muito o que mostrar nos 10 anos passados porque já faz muito tempo que rodo o site inteiro numa VPS, então não tenho uma máquina pra mostrar como no artigo de 10 anos.
Mas posso mostrar o meu eu de 10 anos atrás e o de hoje em dia.
Estou a cada dia mais Maddog Hall que nunca.
Como será que vai ser meu post de 30 anos?
Update: atualizei com uma foto mais ou menos no mesmo ângulo e usando também uma toca, pra ficar no mesmo estilo. Só que errei o ângulo da foto e tive de acertar com o gimp. Como ficou com duas áreas em branco, tive de dar uma adaptada e colar um fundo do Nuketown do Call of Duty.
Como parte da minha cerimônia de renovação, sempre atualizo o tema do site.
Infelizmente a maioria dos temas que existem parecem cada vez mais a mesma coisa. E as opções gratuitas estão cada vez mais limitadas.
Então tive de mudar de um tema escura pra novamente um tema claro.
Mas é ao menos tem alguma atualização.
E novamente vou tentar manter uma frequência maior de posts aqui. Tentarei novamente um post a cada semana no mínimo, o que já exige um esforço fenomenal. Mas o importante é não desistir.
Um vídeo curto com algumas fotos de como foi meu 2020. Por volta de 30 fotos por mês.
Spoiler alert: nada muito emocionante em tempos de COVID.
Um dos trabalhos que faço como voluntário é manter alguns serviços "alternativos" na empresa. Todos baseados em software livre.
Dos que são mantidos temos um mediawiki, um encurtador yourls e um etherpad-lite. E esse último foi o que precisei mexer pra transferir pra um servidor novo.
Muitas pessoas gostam do etherpad-lite e o usam, mas devo dizer que por trás é um lixo. Serviço porco. Ele usa uma só tabela no MySQL/MariaDB com dois campos:
mysql> show tables; +-----------------+ | Tables_in_paddb | +-----------------+ | store | +-----------------+ 1 row in set (0.00 sec) mysql> desc store; +-------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------------+------+-----+---------+-------+ | key | varchar(100) | NO | PRI | | | | value | longtext | YES | | NULL | | +-------+--------------+------+-----+---------+-------+ 2 rows in set (0.01 sec)
Sério. 2 campos. E só. Um é uma chave toscamente preparada pra ser chave primária e o resto... é valor. Então o uso do DB só cresce, sem chances de uma manutenção decente.
Enquanto o uso do etherpad-lite é um dor nas costelas, o assunto é mais da migração dos dados. Então continuando o assunto, o nosso DB chegou ao incrível valor de 13 GB. Daí como faz a migração? O básico é tirar um dump do DB antigo com mysqldump e carregar usando o comand mysql mesmo.
Algo como isso:
# mysql --host=remote-server.mysql.internal.com --port=1234 --user=sqluser --password=sqlpassword mydb < etherpad-migration-backup.sql
que pra todos efeitos funciona. O único problema foi que depois de passar 15 horas carregando o arquivo...
ERROR 2013 (HY000) at line 19057418: Lost connection to MySQL server during query
Dizem que não tem dor maior que a dor do parto. Tem sim e chama-se carregar um dump de 13 GB por 15 horas e falhar. Assim.
E o que restou fazer. Bom... eu sabia a linha onde estava o arquivo, mas já tinham sido 15 horas num arquivo serial, que faz linha por linha. Então decidi quebrar o dump em vários arquivos menores. Dei um rápido "wc -l" no dump e vi que tinham exatamente 28993313 linhas. Então era possível quebrar em 28 arquivos de 1 milhão de linhas cada. E foi o que fiz.
Assim eu sabia que podia continuar do arquivo 20 em diante. E depois resolvia como fazer com o que faltava.
# split -l 1000000 -d etherpad-migration-backup.sql etherpad-migration-backup.sql. # ls -1 pad-migration-backup.sql.?? etherpad-migration-backup.sql.00 etherpad-migration-backup.sql.01 etherpad-migration-backup.sql.02 etherpad-migration-backup.sql.03 etherpad-migration-backup.sql.04 etherpad-migration-backup.sql.05 etherpad-migration-backup.sql.06 etherpad-migration-backup.sql.07 etherpad-migration-backup.sql.08 etherpad-migration-backup.sql.09 etherpad-migration-backup.sql.10 etherpad-migration-backup.sql.11 etherpad-migration-backup.sql.12 etherpad-migration-backup.sql.13 etherpad-migration-backup.sql.14 etherpad-migration-backup.sql.15 etherpad-migration-backup.sql.16 etherpad-migration-backup.sql.17 etherpad-migration-backup.sql.18 etherpad-migration-backup.sql.19 etherpad-migration-backup.sql.20 etherpad-migration-backup.sql.21 etherpad-migration-backup.sql.22 etherpad-migration-backup.sql.23 etherpad-migration-backup.sql.24 etherpad-migration-backup.sql.25 etherpad-migration-backup.sql.26 etherpad-migration-backup.sql.27 etherpad-migration-backup.sql.28 etherpad-migration-backup.sql.29
Com isso eu tive vários arquivos que eu podia subir em paralelo. E foi o que fiz. O resultado? Não só um mas vários erros depois de algumas horas carregando. Eu queria chorar. No chuveiro. Em posição fetal. Só isso.
O maldito do comando mysql não te permite dar um replay descartando o que já existisse no DB, o que seria uma mão na roda nessas situações. Então fiz isso com python. Mas achei que seria lento demais manter serializado. Então era um bom momento pra testar o asyncio, que usei pouquíssimo até hoje. E valeu muito a pena. Esse é o script final:
#! /usr/bin/python3
import sys
import pymysql.cursors
import asyncio
connection = pymysql.connect(host="remote-server.mysql.internal.com",
port=1234,
user="sqluser",
password="sqlpassword",
db="mydb",
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
cursor = connection.cursor()
sema = asyncio.Semaphore(value=10)
async def commit_line(line):
await sema.acquire()
print(line)
try:
cursor.execute(line)
connection.commit()
except:
print("Line (", line[:10],") already inserted")
pass
sema.release()
with open(sys.argv[1]) as sqlfile:
loop = asyncio.get_event_loop()
for line in sqlfile.readlines():
loop.run_until_complete( commit_line(line) )
loop.close()
Não está dos mais polidos, e com senha dentro, mas era uma coisa rápida pra resolver meu problema. E resolveu.
Eu criei uma fila de 10 processos em paralelo pra rodar com: sema = asyncio.Semaphore(value=10)
o controle de acesso ao processo pra rodar é feito com sema.acquire() e sema.release(). Muito fácil. Nem precisei criar um objeto Queue.
Dentro do loop do commit_line() eu sabugue um "enfia essa linha lá ou então continua". Simples assim. E funcionou.
Eu já tinha deixado o tmux aberto com várias janelas, uma pra cada arquivo, então foi só rodar o mesmo em cada uma que falhou.
Levou mais umas 2 ou 3 horas mas carregou tudo.
Foi lindo, não foi?
Esses dias precisei fazer uma migração de uma mediawiki que usamos na empresa de uma máquina que rodava CentOS 6.8 pra um Ubuntu 18.04.
Para garantir seu funcionamento, primeiro eu queria testar os upgrades necessários em minha máquina. Nada melhor que copiar os arquivos e rodar a versão exata do site remoto com containers em docker.
Mas ao rodar o container... ele simplesmente saia com código de erro 139. Mais nada. Sem logs, sem describe, sem nada que pudesse ajudar.
~ > docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8ffcdf12d761 centos:6.8 "bash" 52 minutes ago Up 52 minutes 0.0.0.0:8080->80/tcp elated_ganguly 7bd9374248fd centos:6.8 "bash" 56 minutes ago Exited (139) 56 minutes ago dreamy_fermat 80ff07e9b84e centos:6.8 "bash" 10 hours ago Exited (139) 10 hours ago romantic_hertz 3db1d6c1f68b centos:6 "bash" 10 hours ago Exited (139) 10 hours ago bold_kilby
Olhando pela Internet, descobri em alguns sites pessoas relatando o mesmo problema. É algo relacionado com a versão da glibc do container com a versão do kernel que estou rodando, que é muito mais novo:
~ > uname -a Linux elxa7r5lmh2 5.9.0-rc5-helio #10 SMP Sat Sep 19 12:04:57 CEST 2020 x86_64 x86_64 x86_64 OSI/Linux
A solução é adicionar um parâmetro a mais no grub a opção "vsyscall=emulate":
~ > grep GRUB_CMDLINE_LINUX /etc/default/grub GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 pcie_aspm=off pci=nomsi vsyscall=emulate"
e fazer um update no próprio grub.
~ > sudo update-grub2 && sudo reboot -f
Após um reboot os containers funcionaram sem problemas.
~ > docker run -it --rm=true centos:6.8 bash [root@224aecaba978 /]# hostname 224aecaba978 [root@224aecaba978 /]# exit exit ~ > docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ca68add255bd ubuntu:18.04 "bash" 2 hours ago Exited (1) 2 hours ago festive_galois ~ >
Eu tentei configurar diretamente no kernel através da interface em /sys, mas eu só consegui com isso gerar um kernel panic. O jeito mais fácil e seguro foi mesmo rebootando meu laptop.
Entre os vários grupos do Telegram, um que é muito bom é o de shell, o t.me/shellbr pros mais íntimos.
Um dia desses, entre discussões de como fazer um shell melhor e eu postando sticker pros falantes de língua inglesa de que o grupo é em língua portuguesa, apareceu algo que abriu minha visão em shell pra algo muito maravilhoso. Não é uma novidade de um comando mágico que faz algo completamente novo, mas a simplicidade da solução que esteve esse tempo todo na minha cara e eu nunca vi foi o que me fascinou.
Pra dar um pouco mais de contexto, o que se referia isso: quem nunca precisou mandar um "ps auxwww | grep firefox" e pegou o próprio comando grep na saída?
~> ps auxwww | grep firefox helio 5719 15.5 2.9 3994484 475156 ? Rl 20:57 4:38 /usr/lib/firefox/firefox --ProfileManger --no-remote helio 5815 6.0 1.6 3021712 259472 ? Sl 20:58 1:47 /usr/lib/firefox/firefox -contentproc -childID 1 helio 5876 1.0 1.2 2687192 201516 ? Sl 20:58 0:18 /usr/lib/firefox/firefox -contentproc -childID 2 helio 5916 0.5 1.0 2646492 161856 ? Sl 20:58 0:10 /usr/lib/firefox/firefox -contentproc -childID 3 helio 5939 5.8 2.0 3008700 325944 ? Rl 20:58 1:44 /usr/lib/firefox/firefox -contentproc -childID 4 helio 9210 1.0 1.5 2875692 241532 ? Sl 21:08 0:12 /usr/lib/firefox/firefox -contentproc -childID 9 helio 10161 1.5 1.1 2676620 179336 ? Rl 21:11 0:15 /usr/lib/firefox/firefox -contentproc -childID 10 helio 10394 0.2 0.7 2583360 120484 ? Sl 21:12 0:02 /usr/lib/firefox/firefox -contentproc -childID 11 helio 11818 0.0 0.4 2549948 77524 ? Sl 21:18 0:00 /usr/lib/firefox/firefox -contentproc -childID 13 helio 14368 0.0 0.0 18056 1052 pts/2 S+ 21:27 0:00 grep --color=auto firefox
Comecei com Linux em 1997, quando aprendi a usar as Sparc stations da universidade. Mais de 20 anos nessa indústria vital e eu sempre, sempre, usei desse jeito:
~ > ps auxwww | grep firefox | grep -v grep helio 5719 14.6 3.0 3991196 481364 ? Sl 20:57 4:56 /usr/lib/firefox/firefox --ProfileManger --no-remote helio 5815 6.2 1.7 3019784 279384 ? Sl 20:58 2:05 /usr/lib/firefox/firefox -contentproc -childID 1 helio 5876 0.9 1.2 2687192 202532 ? Sl 20:58 0:19 /usr/lib/firefox/firefox -contentproc -childID 2 helio 5916 0.5 1.0 2646492 164072 ? Sl 20:58 0:10 /usr/lib/firefox/firefox -contentproc -childID 3 helio 5939 5.4 2.0 3008700 330532 ? Sl 20:58 1:49 /usr/lib/firefox/firefox -contentproc -childID 4 helio 9210 0.9 1.5 2875692 241876 ? Sl 21:08 0:13 /usr/lib/firefox/firefox -contentproc -childID 9 helio 10161 1.3 1.1 2676620 179336 ? Sl 21:11 0:16 /usr/lib/firefox/firefox -contentproc -childID 10 helio 10394 0.2 0.7 2583360 120588 ? Sl 21:12 0:02 /usr/lib/firefox/firefox -contentproc -childID 11 helio 11818 0.0 0.4 2549948 77524 ? Sl 21:18 0:00 /usr/lib/firefox/firefox -contentproc -childID 13
Com essa maravilhosa dica do Hélio Campos, basta fazer assim:
~ > ps auxwww | grep [f]irefox helio 5719 14.5 3.1 4005676 500088 ? Sl 20:57 5:01 /usr/lib/firefox/firefox --ProfileManger --no-remote helio 5815 6.7 1.8 3034264 293864 ? Rl 20:58 2:18 /usr/lib/firefox/firefox -contentproc -childID 1 helio 5876 0.9 1.2 2687192 203656 ? Sl 20:58 0:19 /usr/lib/firefox/firefox -contentproc -childID 2 helio 5916 0.5 1.0 2646492 164072 ? Sl 20:58 0:10 /usr/lib/firefox/firefox -contentproc -childID 3 helio 5939 5.3 2.0 3008700 331836 ? Sl 20:58 1:51 /usr/lib/firefox/firefox -contentproc -childID 4 helio 9210 0.9 1.5 2875692 241876 ? Sl 21:08 0:14 /usr/lib/firefox/firefox -contentproc -childID 9 helio 10161 1.3 1.1 2676620 179336 ? Sl 21:11 0:17 /usr/lib/firefox/firefox -contentproc -childID 10 helio 10394 0.2 0.7 2583360 120588 ? Sl 21:12 0:02 /usr/lib/firefox/firefox -contentproc -childID 11 helio 11818 0.0 0.4 2549948 77524 ? Sl 21:18 0:00 /usr/lib/firefox/firefox -contentproc -childID 13
Eu achei espetácular. Pode ser que eu esteja exagerando, mas achei mesmo. Uma dica muito simples e acabou com décadas usando um extra "grep" pra resolver as coisas.
Muito obrigado Hélio Campos e grupo shellbr!
Esses dias eu dei uma boa arrumada na minha estante e encontrei um laptop que estava parado desde 2014. Quando liguei, estava ainda com o Ubuntu 14.04 instalado e rodando. Pensei no mesmo momento que seria perfeito pra verificar o estado da proteção que as distros ditas livres e que são baseadas no GNU Linux Libre possuem.
Eu entrei na página da FSF eu fui seguindo as distros recomendadas como 100% livres. Peguei pra testar as seguintes: Trisquel, Parabola e Guix. Eu ia tentar também a Gnewsense mas a página principal mostra que depois de anos parada seu desenvolvimento foi simplesmente abandonado. Mas ainda está listada na página da FSF.
(Foto By Rafael Bonifaz - Alexandre Oliva, CC BY-SA 2.0,https://commons.wikimedia.org/w/index.php?curid=8939097)
Pra ter alguma comparação eu também testei Debian puro, sem nada a parte de firmwares, e também um Ubuntu. Vou descrever cada um em separado.
Esse morreu na praia pra mim. Como essas distribuições não usam firmwares, não consigo ativar o wifi do laptop. O Guix exige que a instalação siga por rede pra terminar. Eu deixei o laptop numa mesa longe da rede cabeada. Entre mexer o laptop pra minha mesa ou puxar um cabo até o outro quarto eu preferi simplesmente deixar de lado. Tentei procurar por um livecd ou algo do gênero mas não encontrei.
O Trisquel teve a instalação relativamente tranquila. Uma voz robotizada ficava falando tudo o que eu teclava mas deu tudo certo. Como esperado não funcionou com o wifi mas teve o touchpad do laptop funcionado desde a instalação.
uname:
Linux triquel 4.4.0-119-generic #143+8.0trisquel2 SMP Thu Apr 5 16:24:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
cpuinfo:
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel(R) Core(TM) i7-4600M CPU @ 2.90GHz stepping : 3 microcode : 0x16 cpu MHz : 2222.578 cache size : 4096 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_ perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movb e popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb invpcid_single retpoline kaiser tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 e rms invpcid rtm xsaveopt dtherm ida arat pln pts bugs : cpu_meltdown spectre_v1 spectre_v2 bogomips : 5786.73 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management:
vulnerabilidades:
/sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI /sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: OSB (observable speculation barrier, Intel v6) /sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Full generic retpoline
uname:
Linux parabolaiso 5.1.6-gnu-1 #1 SMP PREEMPT Sat Jun 1 21:40:45 UTC 2019 x86_64 GNU/Linux
cpuinfo:
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel(R) Core(TM) i7-4600M CPU @ 2.90GHz stepping : 3 microcode : 0x16 cpu MHz : 1069.269 cache size : 4096 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_ perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe p opcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm xsaveopt dtherm ida arat pln pts bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds bogomips : 5788.69 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management:
vulnerabilidades:
/sys/devices/system/cpu/vulnerabilities/l1tf:Mitigation: PTE Inversion; VMX: conditional cache flushes, SMT vulnerable /sys/devices/system/cpu/vulnerabilities/mds:Vulnerable: Clear CPU buffers attempted, no microcode; SMT vulnerable /sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI /sys/devices/system/cpu/vulnerabilities/spec_store_bypass:Vulnerable /sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: __user pointer sanitization /sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Full generic retpoline, STIBP: disabled, RSB filling
uname:
Linux debian 4.19.0-9-amd64 #1 SMP Debian 4.19.118-2 (2020-04-29) x86_64 GNU/Linux
cpuinfo:
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel(R) Core(TM) i7-4600M CPU @ 2.90GHz stepping : 3 microcode : 0x16 cpu MHz : 1903.637 cache size : 4096 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_ perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe p opcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm xsaveopt dtherm ida arat pln pts bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit bogomips : 5786.32 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management:
vulnerabilidades:
/sys/devices/system/cpu/vulnerabilities/itlb_multihit:KVM: Mitigation: Split huge pages /sys/devices/system/cpu/vulnerabilities/l1tf:Mitigation: PTE Inversion; VMX: conditional cache flushes, SMT vulnerable /sys/devices/system/cpu/vulnerabilities/mds:Vulnerable: Clear CPU buffers attempted, no microcode; SMT vulnerable /sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI /sys/devices/system/cpu/vulnerabilities/spec_store_bypass:Vulnerable /sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: usercopy/swapgs barriers and __user pointer sanitization /sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Full generic retpoline, STIBP: disabled, RSB filling /sys/devices/system/cpu/vulnerabilities/tsx_async_abort:Vulnerable: Clear CPU buffers attempted, no microcode; SMT vulnerable
uname:
Linux ubuntu 4.15.0-29-generic #31-Ubuntu SMP Tue Jul 17 15:39:52 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
cpuinfo:
processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 60 model name : Intel(R) Core(TM) i7-4600M CPU @ 2.90GHz stepping : 3 microcode : 0x16 cpu MHz : 2047.970 cache size : 4096 KB physical id : 0 siblings : 4 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 13 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_ perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe p opcnt aes xsave avx f16c rdrand lahf_lm abm cpuid_fault epb invpcid_single pti tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm xsaveop t dtherm ida arat pln pts bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass bogomips : 5786.49 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management:
vulnerabilidades:
/sys/devices/system/cpu/vulnerabilities/meltdown:Mitigation: PTI /sys/devices/system/cpu/vulnerabilities/spec_store_bypass:Vulnerable /sys/devices/system/cpu/vulnerabilities/spectre_v1:Mitigation: __user pointer sanitization /sys/devices/system/cpu/vulnerabilities/spectre_v2:Mitigation: Full generic retpoline
A comparação é difícil porque cada um dos sistemas operacionais roda com uma versão de kernel diferente. Todas baseadas em Linux.
Todas mostram em cpuinfo que detectam as falhas de spectre_v[1,2] e meltdown, além das demais.
Como mostrado pelas distros com kernels mais recentes, várias vulnerabilidades estão ainda abertas. O sistema continua vulnerável aos ataques de especulação mas não aos spectre v1 e v2, nem meltdown. Realmente sobre essas duas vulnerabilidades o Oliva está certo. Só errou que o restante continua vulnerável e inseguro sem as correções de firmware.
Não imagino que possam ser corrigidas em versões mais recentes pois precisam do firmware da Intel pra mudar o microcode direto na CPU.
Quem continuar utilizando algumas dessas distros é interessante ficar de olho qual bug de CPU foi corrigido e qual ainda está pendente. E ter cuidado ao usar o computador, pois o mesmo continua vulnerável a ataques de especulação mesmo rodando somente software livre.
Page 11 of 35