Falha no disco

Durante um upgrade de uma máquina virtual, o disco principal da máquina falhou. Como as máquinas – a correr em Oracle Virtual Machine – arrancam em modo headless, só percebo a falha porque a máquina não regista, os novos serviços instalados, no meu servidor de logs.

Entrei no VirtualBox, abri uma janela dessa máquina e vi a mensagem – que me aparece de tempos a tempos – a pedir CTRL-D para reboot, ou passwrod de root para manutenção. Introduzi a password e segui os passos indicados neste site para reparar o disco e recuperar a máquina. São os seguintes:

  • Entrar em modo monoutilizador: init 1
  • Desmontar o disco: umount /dev/sda2
  • Verificar o disco: fsck /dev/sda2

Depois, e uma vez que a máquina ainda nem arrancou, fazer reboot.

Slackware 15

Enquanto aguardamos a saída do Slackware 15, o Patrick publicou a seguinte mensagem no Changelog da versão current, enquanto decorria o maior eclipse lunar do século:

Fri Jul 27 21:01:22 UTC 2018
Hey folks, my first order of business here needs to be a huge thank you to
everyone who has donated at https://paypal.me/volkerdi to help keep this
project going. As most of you are already aware by now, the financal situation
here at Slackware HQ has not been great for many years, including not getting
any pay for the last two years and forcing me (and my family) to live very
frugally while I continued to work on the project hoping I’d figure out a way
to actually monitize it by the time that Slackware 15.0 is ready for release.
(…)

Kernel 4.14.47 – II

O ficheiro /etc/rc.d/rc.inet1 está diferente e está a dar problemas. Ainda não identifiquei o problema, por isso tive que reverter a atualização nas 3 máquinas em que isto causou falhas de comunicação.

Além disso, aparentemente, esqueci-me de correr o lilo num dos hosts das máquinas virtuais. Tive que arrancar de DVD e correr os seguintes comandos:

mdadm --assemble --run /dev/md0 /dev/sda2 /dev/sdb2 
mount /dev/md0 /mnt
chroot /mnt
lilo
exit
reboot

Kernel 4.14.47

Nas atualizações a partir da versão current, o Slackware passou a avisar que instalou um novo kernel, mas já não corre o lilo; pede antes que sejamos nós a fazê-lo.

Esqueci-me de fazê-lo em quatro das minhas máquinas virtuais e duas delas não arrancaram. A solução para voltar a arrancar com elas foi semelhante a outra já explicada anteriormente.

Nos settings da máquina, no VirtualBox, pedir para arrancar com o ISO da versão mais recente do Slackware. Depois de entrar, correr os seguintes comandos:

mount /dev/sda2 /mnt
chroot /mnt
lilo
reboot

Perl – IO::Socket::INET segmentation fault

Já há uns meses que tinha este problema pendurado e consegui resolvê-lo hoje.
Tenho 18 máquinas com o Linux Slackware instalado e todas elas têm um script, que corre no arranque e no crontab, e atualiza uma base de dados com as versões dos vários pacotes de software que estão instalados, incluindo a versão do kernel. Assim, consigo saber se me escapou alguma máquina durante as sessões de atualização de software.

Em duas máquinas a atualização da BD não era feita porque o script produzia um segmentation fault ao usar o pacote IO::Socket::INET.

Hoje andei pela net@ a ver como fazer debug de um programa em Perl e descobri que tinha uma diretoria com ficheiros antigos de Perl, nessas duas máquinas, que estavam a causar o problema.

Com o debug, encontrei a origem do erro:

# perl -d bat/kern2.pl

Loading DB routines from perl5db.pl version 1.51
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

Signal SEGV at /usr/local/lib64/perl5/Socket.pm line 858.
        require Socket.pm called at /usr/lib64/perl5/IO/Socket.pm line 13
        IO::Socket::BEGIN() called at /usr/local/lib64/perl5/Socket.pm line 0
        eval {...} called at /usr/local/lib64/perl5/Socket.pm line 0
        require IO/Socket.pm called at /usr/lib64/perl5/IO/Socket/INET.pm line 11
        IO::Socket::INET::BEGIN() called at /usr/local/lib64/perl5/Socket.pm line 0
        eval {...} called at /usr/local/lib64/perl5/Socket.pm line 0
        require IO/Socket/INET.pm called at bat/kern2.pl line 3
        main::BEGIN() called at /usr/local/lib64/perl5/Socket.pm line 0
        eval {...} called at /usr/local/lib64/perl5/Socket.pm line 0
Aborted

O erro estava na linha 858 do ficheiro /usr/local/lib64/perl5/Socket.pm.

Decidi ver se havia diferenças, entre máquinas, nas diretorias de INCLUDE e corri o comando seguinte:

# perl -E'say for @INC'
/usr/local/lib64/perl5
/usr/local/share/perl5
/usr/lib64/perl5/vendor_perl
/usr/share/perl5/vendor_perl
/usr/lib64/perl5
/usr/share/perl5

Mas as diretorias eram as mesmas tanto nas máquinas que corriam o script, como nas que não corriam.

Então, fui ver se o ficheiro onde o erro ocorria – /usr/local/lib64/perl5/Socket.pm – era diferente entre máquinas, se, por exemplo, a linha 858 era igual entre ficheiros. E descobri que o ficheiro /usr/local/lib64/perl5/Socket.pm só existia nas máquinas que não corriam o script. Nas outras máquinas, a diretoria /usr/local/lib64/perl5/ estava vazia. Apaguei o conteúdo dessa diretoria nas máquinas-problema, e o problema desapareceu.

Há muitos anos atrás, tive que instalar o pacote IO::Socket::INET e outros, nessas máquinas, para poder comunicar pela rede, mas agora esses pacotes fazem parte do núcleo do Perl. Os pacotes antigos estavam a sobrepor-se aos do núcleo e estavam a gerar o erro.

Recuperar RAID 1

Tive problemas com o RAID de uma das máquinas. Por algum motivo, um dos discos saltou fora do RAID 1.
Fui à procura na net e encontrei dois sítios com informação importante:
Replacing A Failed Hard Drive In A Software RAID1 Array
How to check ‘mdadm’ RAIDs while running?

Ao emitir o comando cat /proc/mdstat o resultado foi o seguinte:

md2 : active raid1 sdf1[1] sde1[0]
      1953512400 blocks super 1.2 [2/2] [UU]

md3 : active raid1 sdd1[1]
      1953512400 blocks super 1.2 [2/1] [_U]

md0 : active raid1 sda3[0] sdb3[1]
      73939072 blocks [2/2] [UU]

No md3 faltava o sdc1. Se estivesse lá, mas com erro, teria que ser removido primeiro, com os comandos sguintes:

mdadm --manage /dev/md3 --fail /dev/sdc1
mdadm --manage /dev/md3 --remove /dev/sdc1

E depois, desligaria a máquina e, se o disco estivesse mesmo avariado, trocaria o disco.
É necessário criar uma partição igual à da partição sdd1. Para comparar as partições, emitir o comando fdisk -l, cujo resultado, para os discos em causa, é:

Disk /dev/sdc: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x98f9dba0

Device     Boot Start        End    Sectors  Size Id Type
/dev/sdc1        2048 3907029167 3907027120  1.8T fd Linux raid autodetect


Disk /dev/sdd: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xbe1f7c22

Device     Boot Start        End    Sectors  Size Id Type
/dev/sdd1        2048 3907029167 3907027120  1.8T fd Linux raid autodetect

A partir daí, e para recolocar o disco novamente no RAID, o comando é o seguinte:

mdadm --manage /dev/md3 --add /dev/sdc1

A reconstrução do RAID é iniciada. Pode-se ir acompanhando o processo com o comando cat /proc/mdstat

md2 : active raid1 sdf1[1] sde1[0]
      1953512400 blocks super 1.2 [2/2] [UU]

md3 : active raid1 sdc1[2] sdd1[1]
      1953512400 blocks super 1.2 [2/1] [_U]
      [=============>.......]  recovery = 66.1% (1291278848/1953512400) finish=142.0min speed=77670K/sec

md0 : active raid1 sda3[0] sdb3[1]
      73939072 blocks [2/2] [UU]

ou então com o comando mdadm -D /dev/md3:

/dev/md3:
        Version : 1.2
  Creation Time : Sat Mar 10 21:20:35 2012
     Raid Level : raid1
     Array Size : 1953512400 (1863.01 GiB 2000.40 GB)
  Used Dev Size : 1953512400 (1863.01 GiB 2000.40 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Wed Apr 25 12:51:45 2018
          State : clean, degraded, recovering
 Active Devices : 1
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 1

 Rebuild Status : 65% complete

           Name : tao:3
           UUID : 90d1dc37:d4fd77a4:a4a1d0fe:98a3717d
         Events : 68048

    Number   Major   Minor   RaidDevice State
       2       8       33        0      spare rebuilding   /dev/sdc1
       1       8       49        1      active sync   /dev/sdd1

VirtualBox 5.2.10

Vou atualizar o VirtualBox nos dois hosts de máquinas virtuais. Eis os comandos:

cd /root
bat/vboxes stop
cd /usr/local/
VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack"
reboot
exit
cd /usr/local/
chmod +x ./VirtualBox-5.2.10-122088-Linux_amd64.run
./VirtualBox-5.2.10-122088-Linux_amd64.run
VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-5.2.10.vbox-extpack
cd /root
bat/vboxes start

O ficheiro bat/vboxes é um ficheiro de comandos que criei para gerir as máquinas virtuais do VirtualBox.

Postfix e outras atualizações

Como ainda não tive tempo de estudar a configuração completa do postfix, neste momento mantenho o sendmail, assim como a versão antiga do imapd, ao invés do dovecot.

Assim, no principal servidor de email, não instalo os pacotes postfix, nem dovecot. E não desinstalo o imapd, nem o sendmail. Se por acaso algo falhar numa atualização, removo os dois primeiros e uso as últimas versões do sendmail e do imapd:

removepkg postfix-3.3.0-x86_64-3.txz
removepkg dovecot-2.3.1-x86_64-3.txz

installpkg sendmail-8.15.2-x86_64-2.txz
installpkg sendmail-cf-8.15.2-noarch-2.txz
installpkg imapd-2.20-x86_64-2.txz

Noutra máquina, tenho uma aplicação Web que recebe um ficheiro cifrado com uma função que o PHP descartou a partir da versão 7.1.0. Assim, nessa máquina, não devo atualizar o PHP, enquanto não arranjar solução alternativa. Caso me esqueça, aqui fica a solução para reverter a versão:

removepkg php-7.2.4-x86_64-2.txz
installpkg php-5.6.23-x86_64-1.txz
cp /tmp/mod_php.conf.example /etc/httpd/mod_php.conf

Costumo guardar os ficheiros das versões antigas na pasta /tmp.

Configurar o Postfix

O Slackware passou a usar o Postfix, em vez do Sendmail como ferramenta de MTA. Eu já tinha uma série de configurações complexas dos meus servidores com o Sendmail e deixei de conseguir enviar emails de todos eles. Todos eles faziam Relay através de um servidor já aceite pelos grandes serviços de email da rede, nomeadamente pelo hotmail da Microsoft, com quem tive que assinar um acordo de não Spam.

Agora com o Postfix, tenho que reconfigurar tudo de novo. Para já fica aqui registado o processo que usei para conseguir enviar emails para fora.

No ficheiro /etc/postfix/main.cf adicionei as linhas seguintes, no fim do ficheiro:

mynetworks = 127.0.0.0/8 192.168.0.0/16
smtp_generic_maps = hash:/etc/postfix/generic
smtpd_client_restrictions = permit_mynetworks, reject

No ficheiro /etc/postfix/generic adicionei a linha seguinte, no fim do ficheiro:

@localhost eu@meuservidor.pt
maria@localhost maria@meuservidor.pt

Depois, foi necessário criar o ficheiro /etc/postfix/generic.db pois comecei a receber o erro abaixo, quando lançava o servidor Postfix:

Postfix: error: open database /etc/postfix/generic.db: No such file or directory

Para criar o ficheiro /etc/postfix/generic.db usei a linha de comando seguinte:

postmap /etc/postfix/generic

Por fim, relancei o Postfix:

postfix stop
postfix start

Ainda faltam muitas configurações, nomeadamente, os ACCEPT e REJECT do ficheiro access.db do Sendmail, assim como o reencaminhamento de outros servidores para o servidor principal. Mas isso fica para uma próxima crónica.