Como posso depurar remotamente um initrd quebrado?

2

Antecedentes

Eu tenho um sistema que executa o Linux. É um NAS e não possui nenhum monitor, teclado ou porta serial. Tem uma porta de rede. Eu não estou feliz com o software em execução e estou tentando obter uma distro diferente para executar.

O que eu tenho

No sistema existente, consigo obter um novo kernel e initrd inicializado, usando a interface da web para atualizar a ROM, mas essa atualização é uma imagem especialmente criada, que nada mais faz do que descompactar um kernel, initrd, kexec e executa kexec com os argumentos necessários para inicializar o novo kernel.

O initrd configura uma conexão de rede, inicia um servidor SSH (dropbear) e aguarda que termine. Em seguida, ele executa um script diferente. Usando isso, posso fazer alguns testes: posso inicializar nesse kernel / initrd, efetuar login via SSH, personalizar o script do estágio 2, matar o dropbear e esperar pelo melhor.

Usando essa abordagem, consegui instalar um sistema operacional funcional no disco rígido. (Por enquanto, é o NixOS, se é importante, mas eu posso mudar isso no futuro. Minha pergunta não é sobre qualquer distribuição específica.) Eu intencionalmente não tornou inicializável. Eu gostaria de manter a memória flash como está, de modo que, além dos dados no disco rígido, o NAS permaneça "oficial". Eu, no entanto, obtive o kernel e o initrd da própria distro, que eu gostaria de colocar uma imagem de atualização.

O problema

Usando esse kernel e initrd, o sistema não inicia.

Minhas tentativas

Eu montei um initrd compartilhado, contendo a configuração da distro, assim como a minha própria, que continua sendo inicializada em dropbear. Em um shell SSH, eu então tento executar os scripts de inicialização da distro. Isso falha, no entanto, porque depende de ser executado como PID 1.

Eu então tentei fazer com que o PID 1 tomasse comandos arbitrários: eu fiz ele rodar scripts de um pipe, e escrevi para aquele pipe a partir do meu shell remoto, com a intenção de inspecionar manualmente se o comando tinha o efeito desejado. No entanto, isso não funciona: o shell de inicialização (PID 1) vê EOF após o primeiro comando e sai imediatamente. Olá pânico do kernel.

Eu também tentei testar o que aconteceria se eu fizesse isso não importasse se ele estava sendo executado como PID 1, passando a opção --system do systemd e, em seguida, executando o script de inicialização da distro do meu shell. Dessa forma, não consegui reproduzir o problema: funcionou.

Minha pergunta: e agora?

Neste ponto, estou olhando para a abordagem de pipe para uma alternativa, algo que realmente funciona para executar mais de um comando. De preferência, algo que também me permite ver a saída dos comandos.

Basicamente: Eu quero saber como posso ver remotamente a saída dos programas de inicialização que são executados a partir do PID 1, que não podem ser executados em uma sessão SSH, sem na verdade anexar um monitor ou um cabo serial.

Respostas que adotam uma abordagem completamente diferente também são bem-vindas, mas tenha em mente as restrições do sistema com as quais estou lidando. Eu não apenas não tenho um monitor ou cabo serial, eu nem tenho uma porta serial ou VGA. Eu tenho uma porta USB na qual eu poderia conectar um teclado, se necessário, mas obviamente não consigo ver nada que eu digite.

    
por hvd 30.07.2014 / 00:09

2 respostas

0

Depois de iniciar uma sessão SSH, outras sessões também podem ser escritas lá, escrevendo para /dev/pts/<N> . Então, para ver o que está acontecendo, já que eu já sou capaz de controlar o que o PID 1 vai acabar funcionando, eu só preciso fazer com que ele seja escrito lá. Usando exec 0<>/dev/pts/0 1<>/dev/pts/0 2<>/dev/pts/0 do PID 1 e certificando-se de que nada mais esteja lendo / escrevendo lá, posso ver o que está acontecendo. Quando, eventualmente, falha, o script de inicialização da distro pede para perguntar o que fazer, e até me responde apropriadamente digitando R para reinicializar.

O problema real que eu estava tendo parece ter sido causado por módulos do kernel necessários que não foram carregados. Embora eu conseguisse fazer tudo funcionar manualmente, o que obviamente significa que o bloco, o RAID e os módulos do sistema de arquivos estavam disponíveis e sendo carregados, o script da distribuição depende do udev, e requer alguns módulos adicionais, em particular unix ( que eu nunca teria me escolhido para não construir no kernel).

    
por 02.08.2014 / 10:28
0

A idéia geral para fazer isso é substituir o init por um script que gera o script inicial baseado em initrd em segundo plano, continua a montar a raiz do sistema e faz [-x / root / sbini / init] & ; exec chroot / root / sbin / init. (Coloque algum código abaixo para lidar com isso não existente.)

    
por 30.07.2014 / 17:08