Tirei férias longas demais. Na verdade foram apenas 3 semanas, mas eu meio que deixei de postar aqui durante o período de férias. E a procrastinação voltou forte. Então aqui vamos nós com uma tentativa de voltar a escrever semanalmente.
Hoje, fazendo um troubleshooting the um serviço que não funcionava como devia (um scan de aplicação com o OWASP ZAP), descobri que meus containers em docker não estavam acessando a rede. O que mudou? Minha máquina de trabalho é um Ubuntu 18.04. O repositório bionic-update trouxe uma versão nova do docker que reiniciou o daemon, mas... a parte de rede não funcionando. E só percebi isso hoje.
root@dell-latitude-7480 /u/local# apt show docker.io Package: docker.io Version: 20.10.7-0ubuntu1~18.04.1 Built-Using: glibc (= 2.27-3ubuntu1.2), golang-1.13 (= 1.13.8-1ubuntu1~18.04.3) Priority: optional Section: universe/admin Origin: Ubuntu Maintainer: Ubuntu Developers <This email address is being protected from spambots. You need JavaScript enabled to view it. > Original-Maintainer: Paul Tagliamonte <This email address is being protected from spambots. You need JavaScript enabled to view it. > Bugs: https://bugs.launchpad.net/ubuntu/+filebug Installed-Size: 193 MB Depends: adduser, containerd (>= 1.2.6-0ubuntu1~), iptables, debconf (>= 0.5) | debconf-2.0, libc6 (>= 2.8), libdevmapper1.02.1 (>= 2:1.02.97), libsystemd0 (>= 209~) Recommends: ca-certificates, git, pigz, ubuntu-fan, xz-utils, apparmor Suggests: aufs-tools, btrfs-progs, cgroupfs-mount | cgroup-lite, debootstrap, docker-doc, rinse, zfs-fuse | zfsutils Breaks: docker (<< 1.5~) Replaces: docker (<< 1.5~) Homepage: https://www.docker.com/community-edition Download-Size: 36.9 MB APT-Manual-Installed: yes APT-Sources: mirror://mirrors.ubuntu.com/mirrors.txt bionic-updates/universe amd64 Packages Description: Linux container runtime Docker complements kernel namespacing with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. . Docker is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc. . This package contains the daemon and client. Using docker.io on non-amd64 hosts is not supported at this time. Please be careful when using it on anything besides amd64. . Also, note that kernel version 3.8 or above is required for proper operation of the daemon process, and that any lower versions may have subtle and/or glaring issues. N: There is 1 additional record. Please use the '-a' switch to see it
Primeira coisa que tentei foi reiniciar o docker mesmo.
root@dell-latitude-7480 /u/local# systemctl restart --no-block docker; journalctl -u docker -f [...] Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.203367946+02:00" level=info msg="Firewalld: docker zone already exists, returning" Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.549158535+02:00" level=warning msg="could not create bridge network for id 88bd200
b5bb27d3fd10d9e8bf86b1947b2190cf7be36cd7243eec55ac8089dc6 bridge name docker0 while booting up from persistent state: Failed to program NAT chain:
ZONE_CONFLICT: 'docker0' already bound to a zone" Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.596805407+02:00" level=info msg="stopping event stream following graceful shutdown"
error="" module=libcontainerd namespace=moby Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.596994440+02:00" level=info msg="stopping event stream following graceful shutdown"
error="context canceled" module=libcontainerd namespace=plugins.moby Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: failed to start daemon: Error initializing network controller: Error creating default "bridge" network:
Failed to program NAT chain: ZONE_CONFLICT: 'docker0' already bound to a zone Aug 12 10:29:25 dell-latitude-7480 systemd[1]: docker.service: Main process exited, code=exited, status=1/FAILURE Aug 12 10:29:25 dell-latitude-7480 systemd[1]: docker.service: Failed with result 'exit-code'. Aug 12 10:29:25 dell-latitude-7480 systemd[1]: Failed to start Docker Application Container Engine. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Service hold-off time over, scheduling restart. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Scheduled restart job, restart counter is at 3. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: Stopped Docker Application Container Engine. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Start request repeated too quickly. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Failed with result 'exit-code'. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: Failed to start Docker Application Container Engine.
As linhas estão editadas pra facilitar a visualização uma vez que o systemd usa linhas bem maiores que 120 colunas. Mas o resultado foi... falha.
Parando o firewalld e somente reiniciando docker levava a uma condição em que o daemon iniciava, mas ao iniciar o container, novamente ficava sem acesso à rede.
root@dell-latitude-7480 /u/local# docker run -it --rm --init ubuntu:20.04 bash root@f45dcbb1ecaa:/# ping 1.1.1.1 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. ^C --- 1.1.1.1 ping statistics --- 6 packets transmitted, 0 received, 100% packet loss, time 5153ms root@f45dcbb1ecaa:/# exit
Olhando somente as regras do firewall eu pude ver que realmente o docker estava carregando a regra correta sem o firewalld:
root@dell-latitude-7480 /u/local# systemctl stop firewalld.service root@dell-latitude-7480 /u/local# iptables -L -n -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination Chain POSTROUTING (policy ACCEPT) target prot opt source destination root@dell-latitude-7480 /u/local# systemctl restart docker root@dell-latitude-7480 /u/local# systemctl status docker ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Thu 2021-08-12 12:01:12 CEST; 4s ago Docs: https://docs.docker.com Main PID: 484649 (dockerd) Tasks: 27 CGroup: /system.slice/docker.service └─484649 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061383466+02:00" level=warning msg="Your kernel does not support swap memory limit" Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061414030+02:00" level=warning msg="Your kernel does not support CPU realtime scheduler" Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061421558+02:00" level=warning msg="Your kernel does not support cgroup blkio weight" Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061427194+02:00" level=warning msg="Your kernel does not support cgroup blkio weight_device" Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061796106+02:00" level=info msg="Loading containers: start." Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.531851162+02:00" level=info msg="Loading containers: done." Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.549979768+02:00" level=info msg="Docker daemon" commit="20.10.7-0ubuntu1~18.04.1" graphdriver(s)=overlay2 version=20.10.7 Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.550057275+02:00" level=info msg="Daemon has completed initialization" Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.558188106+02:00" level=info msg="API listen on /var/run/docker.sock" Aug 12 12:01:12 dell-latitude-7480 systemd[1]: Started Docker Application Container Engine. root@dell-latitude-7480 /u/local# iptables -L -n -t nat Chain PREROUTING (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination DOCKER all -- 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT) target prot opt source destination MASQUERADE all -- 172.16.0.0/24 0.0.0.0/0 Chain DOCKER (2 references) target prot opt source destination RETURN all -- 0.0.0.0/0 0.0.0.0/0
Claramente existia uma regra de MASQUERADE vinda da rede do docker (172.16.0.0/24). E o firewalld estava sumindo com essa regra ao ser ativado (pra ficar menos poluído com várias regras peguei só a saída da cadeia do POSTROUTING.
root@dell-latitude-7480 /u/local# systemctl start firewalld.service root@dell-latitude-7480 /u/local# iptables -L POSTROUTING -n -t nat Chain POSTROUTING (policy ACCEPT) target prot opt source destination POSTROUTING_direct all -- 0.0.0.0/0 0.0.0.0/0 POSTROUTING_ZONES_SOURCE all -- 0.0.0.0/0 0.0.0.0/0 POSTROUTING_ZONES all -- 0.0.0.0/0 0.0.0.0/0
A minha primeira ideia: inserir à força uma regra de MASQUERADE direto na cadeia de POSTROUTING.
root@dell-latitude-7480 /u/local# iptables -I POSTROUTING 1 -s 172.16.0.0/24 -j MASQUERADE -t nat root@dell-latitude-7480 /u/local# iptables -L POSTROUTING --line-numbers -t nat Chain POSTROUTING (policy ACCEPT) num target prot opt source destination 1 MASQUERADE all -- 172.16.0.0/24 anywhere 2 POSTROUTING_direct all -- anywhere anywhere 3 POSTROUTING_ZONES_SOURCE all -- anywhere anywhere 4 POSTROUTING_ZONES all -- anywhere anywhere
E, claro, não deu certo.
Depois de procurar na Internet sobre docker e firewalld, encontrei o próprio site do Docker explicando como fazer isso em https://docs.docker.com/network/iptables/ com o seguinte comando:
# Please substitute the appropriate zone and docker interface $ firewall-cmd --zone=trusted --remove-interface=docker0 --permanent $ firewall-cmd --reload
Beleza. Agora não teria como dar errado. E...
root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0 public root@dell-latitude-7480 /u/local# firewall-cmd --zone=public --remove-interface=docker0 --permanent The interface is under control of NetworkManager and already bound to the default zone The interface is under control of NetworkManager, setting zone to default. success root@dell-latitude-7480 /u/local# systemctl start docker Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xe" for details.
Caramba... algo de errado não estava certo. Bom... se tivesse funcionado de primeira, eu provavelmente não teria escrito esse artigo.
Então vamos rever em qual zona está a interface docker0, remover essa interface dessa zona e adicionar na zona do docker.
root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0 public root@dell-latitude-7480 /u/local# firewall-cmd --zone=public --remove-interface=docker0 --permanent The interface is under control of NetworkManager and already bound to the default zone The interface is under control of NetworkManager, setting zone to default. success root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0 public root@dell-latitude-7480 /u/local# firewall-cmd --reload success root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0 public
Mas que catzo... esse foi problema que encontrei. Por mais que eu removesse ou tentasse remover a interface docker0 da zone public, sempre voltava.
Foram algumas horas nesse vai e vem, procurando na Internet o que fazer, lendo documentação do firewalld, até que finalmente acertei.
root@dell-latitude-7480 /u/local# firewall-cmd --zone=docker --add-interface=docker0 --permanent The interface is under control of NetworkManager, setting zone to 'docker'. success root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0 docker root@dell-latitude-7480 /u/local# firewall-cmd --reload success root@dell-latitude-7480 /u/local# systemctl start docker
Então não precisava do comando pra remover. Apenas adicionar diretamente na zona desejada.
root@dell-latitude-7480 /u/local# docker run -it --rm --init ubuntu:20.04 bash root@e5d78d7f081b:/# ping -c 5 1.1.1.1 PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data. 64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=1.95 ms 64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=2.02 ms 64 bytes from 1.1.1.1: icmp_seq=3 ttl=58 time=1.68 ms 64 bytes from 1.1.1.1: icmp_seq=4 ttl=58 time=1.62 ms 64 bytes from 1.1.1.1: icmp_seq=5 ttl=58 time=1.76 ms --- 1.1.1.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4003ms rtt min/avg/max/mdev = 1.621/1.808/2.026/0.162 ms root@e5d78d7f081b:/# exit
E minhas aventuras com LVM continuam. Um dos HDDs começou a chiar. Mas chiar mesmo, fazendo barulho de marteladas e resets. Olhando nos logs eu vi que já tinha dado o que tinha que dar. E justamente o HDD que fazia parte do mirroring em que estão os jogos da steam.
Então procedi com o comando pra terminar a montagem em mirroring.
lvconvert -m 0 diskspace/steam /dev/sdb3
Infelizmente eu dei um reboot em seguida e não salvei nada pra poder postar aqui. Mas o mais importante foi depois de removido HDD e instalado um novo (também de 2 TB) que tinha parado aqui. Como eu esqueci de remover o /dev/sdb3 do LVM, claro que subiu com vários erros. Particionei o novo HDD (/dev/sdb) com uma só partição LVM. E fui adicionar quando...
root@goosfraba ~# pvcreate /dev/sdb1
WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
Physical volume "/dev/sdb1" successfully created.
Epa! Que catzo de CvlXC4-não-sei-lá-o-que é esse? Sim, o disco que removi fisicamente e não tirei logicamente do LVM. Com "vgdisplay" pude ver que realmente o problema estava lá.
root@goosfraba ~# vgdisplay
WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
--- Volume group ---
VG Name diskspace
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 230
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 9
Open LV 2
Max PV 0
Cur PV 2
Act PV 1
VG Size 5.45 TiB
PE Size 4.00 MiB
Total PE 1429493
Alloc PE / Size 518912 /
Resolver não foi nada complicado. Bastou o seguinte comando:
root@goosfraba ~# vgreduce --removemissing diskspace
WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
Wrote out consistent volume group diskspace.
Pronto! Metadados do disco antigo removidos.
root@goosfraba ~# vgdisplay
--- Volume group ---
VG Name diskspace
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 231
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 9
Open LV 2
Max PV 0
Cur PV 1
Act PV 1
VG Size
Agora o trabalho seguinte foi adicionar o espaço novo dentro do VG (diskspace é o nome):
root@goosfraba ~# vgextend diskspace /dev/sdb1
Volume group "diskspace" successfully extended
root@goosfraba ~# vgdisplay
--- Volume group ---
VG Name diskspace
System ID
Format lvm2
Metadata Areas 2
Metadata Sequence No 232
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 9
Open LV 2
Max PV 0
Cur PV 2
Act PV 2
VG Size
Em seguida colocar o disco novo como mirroring novamente:
root@goosfraba ~# lvconvert -m 1 /dev/diskspace/steam /dev/sdb1
Are you sure you want to convert linear LV diskspace/steam to raid1 with 2 images enhancing resilience? [y/n]: y
Logical volume diskspace/steam successfully converted.
E pronto. Acabou. Isso mesmo. Foi fácil assim. Agora é só ir monitorando o progresso da cópia no disco novo.
root@goosfraba ~# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
home diskspace -wi-a----- 500.00g
opt diskspace -wi-a----- 2.00g
root diskspace -wi-ao---- 10.00g
steam diskspace rwi-a-r--- 750.00g 0.88
swap diskspace -wi-a----- 15.00g
tmp diskspace -wi-a----- 5.00g
usr diskspace -wi-ao---- 95.00g
usrlocal diskspace -wi-a----- 600.00g
var diskspace -wi-a----- 50.00g
root@goosfraba ~# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
home diskspace -wi-a----- 500.00g
opt diskspace -wi-a----- 2.00g
root diskspace -wi-ao---- 10.00g
steam diskspace rwi-a-r--- 750.00g 1.10
swap diskspace -wi-a----- 15.00g
tmp diskspace -wi-a----- 5.00g
usr diskspace -wi-ao---- 95.00g
usrlocal diskspace -wi-a----- 600.00g
var diskspace -wi-a----- 50.00g
Como são 750 GB a coisa demora um pouco. Mas com LVM, tudo é muito fácil.
Happy hacking :)
Essa dúvida surgiu no grupo de Ubuntu do Telegram (https://t.me/ulboficial) e ao invés de responder lá eu preferi escrever um artigo sobre isso.
O método que uso, principalmente em laptops novos, é basicamente o mesmo desde... acho que aprendi a fazer isso por volta dos anos 2000. Era um capítulo do venerado livro "Unix Power Tools", a bíblia dos scripts pra sysadmins.
Eu primeiramente insiro o HD novo e particiono. Não vou usar o exemplo de LVM, que é mais simples, mas o mais cabeludo que é quando se cria todas as partições que vai usar. Então digamos que eu adicione um novo HD que aparecerá para mim como /dev/sdb (pra facilitar). Supondo que o particionamento seja o seguinte:
O passo seguinte, após formatar as partições no formato desejado (eu geralmente uso XFS), é montar essas partições em um local onde possa copiar os dados. Eu normalmente uso o /mnt pra essa finalidade.
root@goosfraba ~# mount /dev/sdb5 /mnt
root@goosfraba ~# mount /dev/sdb1 /mnt/boot
root@goosfraba ~# mount /dev/sdb6 /mnt/home
Uma vez com tudo montado é fazer cópia de um lado pro outro evitando copiar o /mnt, que já está em uso com o disco novo, e diretórios como /proc, /dev ou /sys, que são criados durante o boot. E pra isso eu uso o comando tar.
root@goosfraba ~# tar cvf - --exclude=./proc --exclude=./sys --exclude=./dev --exclude=./mnt -C / . | tar xf -C /mnt
Com isso o disco já está todo pronto em /mnt. Resta corrigir o boot. Pra isso eu uso chroot pra acessar o disco novo a partir de /mnt e montando tanto /proc quanto /dev pro grub localizar o disco corretamente.
root@goosfraba ~# mkdir /mnt/{proc, dev}
root@goosfraba ~# mount --bind /proc /mnt/proc
root@goosfraba ~# mount --bind /dev /mnt/dev
root@goosfraba ~# chroot /mnt
root@chroot ~$ grub-install /dev/sdb
Assumindo que vá remover o primeiro disco, /dev/sda, e sdb será o novo sda, nada mais é preciso. Agora caso vá ficar com sdb como disco principal, então é preciso modificar as entradas do /etc/fstab pra conter os dados corretos do novo disco.
Ao terminar e antes de rebootar, tenha com você o disco de instalação em mãos pra utilizar o modo de recuperação em caso de algum problema (e não precisar ficar colocando o disco antigo).
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.
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.