1 pontos por GN⁺ 2024-07-30 | 1 comentários | Compartilhar no WhatsApp
  • izabera/ps é uma implementação em Bash para imitar, dentro do Bash, uma saída próxima de ps aux mesmo em situações em que não é possível criar novos processos
  • A condição principal é um cenário em que há um bash shell confiável em uma máquina acessada via ssh, mas todos os outros PIDs estão em uso e não é possível criar um novo processo
  • O README apresenta essa situação como um exemplo de pergunta de entrevista para uma vaga que exige conhecimentos de Bash/Linux
  • A ferramenta é descrita como algo que permite “fingir mais ou menos” que se tem acesso a um ps aux funcional, sem garantir que seja uma implementação substituta completa
  • A frase “funciona 100% em todas as máquinas e em todas as situações” é claramente usada como uma garantia em tom de brincadeira

Que tipo de projeto é este

  • É um projeto que implementa ps aux apenas com Bash
  • O título do README é “ps aux written entirely in bash without ever forking”
  • A principal característica do projeto é que ele não faz fork em nenhum momento durante a execução

Situação considerada

  • O cenário de exemplo é o seguinte
    • Você está conectado à máquina via ssh
    • O usuário está em um bash shell familiar
    • Mas todos os outros PIDs estão em uso, então não é possível criar nenhum novo processo
  • O README apresenta que, nessas condições, pode ser necessário algo parecido com ps aux

Escopo esperado e ressalvas

  • A ferramenta é apresentada como uma forma de “kinda sorta pretend” que existe um ps aux funcional
  • A frase do README dizendo que é “garantido funcionar perfeitamente em 100% das máquinas, em todas as situações” é usada como humor exagerado
  • Portanto, o ponto central da descrição não é compatibilidade completa, mas sim imitar ps aux apenas com Bash em um ambiente extremo no qual não é possível criar novos processos

1 comentários

 
GN⁺ 2024-07-30
Opiniões no Hacker News
  • A piada de que o problema mais difícil da ciência da computação acabou sendo alinhar colunas faz sentido
    Já escrevi inúmeras funções de alinhamento de colunas em várias linguagens, e sempre foi sofrido; na cabeça parece simples, algo como “calcular o maior comprimento de cada coluna e inserir espaços até o próximo múltiplo do tamanho da tabulação”
    Mesmo usando f-strings e recursos de padding do Python, o código rapidamente fica complexo e difícil de ler; é tão horrível que, enquanto reescrevia um exemplo para um comentário, corrigi vários bugs

    • Já cheguei a adicionar Pandas a um projeto só para não ter de escrever esse tipo de código manualmente para imprimir tabelas bonitas
      Para um uso tão comum, parece óbvio que deveria haver uma biblioteca; sinceramente, é surpreendente que isso não exista na biblioteca padrão
    • https://perldoc.perl.org/perlform
    • Há algum tempo respondi no Stack Overflow com uma solução O(n): https://stackoverflow.com/questions/10865483/print-results-i...
      A abordagem extrai as larguras e os nomes das colunas a partir do description do cursor do banco de dados, monta a linha separadora e a string de formato e então imprime as linhas; não sei se há algum bug fatal que eu tenha deixado passar, e não parece um problema especialmente difícil
    • De forma ainda mais simples, dá para usar zip(*table) para transpor as colunas, calcular o maior comprimento de cada uma e imprimir alinhado com f"{r:<{w}}"
      O resultado de exemplo vira uma tabela com larguras de coluna alinhadas, como agony | kick | pump
    • Por outro lado, para quem precisa fazer parsing frequente de dados alinhados em colunas, isso também não é fácil
      Os valores contêm espaços, são preenchidos com espaços e, às vezes, o alinhamento sai errado ou os dados transbordam a coluna
      Talvez fosse melhor todos combinarmos de não usar dados alinhados em colunas e adotar um formato mais simples e legível por humanos; todos sairiam ganhando
  • Se eu entrasse por SSH em uma máquina na qual o shell Bash ainda está vivo, mas todos os PIDs foram esgotados e não é possível criar novos processos, eu vasculharia o sistema de arquivos /proc/[pid]/ para descobrir qual processo está esgotando o espaço de PIDs
    O kill do Bash é um comando embutido do shell, então não precisa fazer fork de um novo processo como /bin/kill
    Se for possível encontrar o processo pai que está gerando os filhos que esgotam os PIDs, dá para interrompê-lo e recuperar o controle do sistema
    Este script também faz parsing de /proc e não usa pipes nem substituições $(...) que criariam um novo subshell Bash, então é bem limpo

    • Em uma entrevista, certa vez respondi “exec Python
      Assim, seria possível chamar as funções POSIX necessárias sem executar um comando separado, o que gerou uma boa reação
    • Sinceramente, eu provavelmente apenas reiniciaria
      Reiniciar e recuperar depois pode ser mais rápido do que encontrar e matar o processo pai em um ambiente restrito; se os PIDs acabaram, é provável que outras coisas também já estejam em mau estado
    • Para ver apenas o PID e o nome do comando, dá para fazer algo quase mínimo assim: ps(){ (cd /proc;for i in [0-9]*;do echo $i: $(tr '\0' ' ' < $i/cmdline);done); }
    • A ideia de olhar em /proc/[pid]/ para ver qual processo está esgotando o espaço de PIDs está correta, mas pelos comentários no código-fonte parece que inicialmente se esperava que apenas /proc/*/status fosse suficiente; valores como uso de CPU, porém, não podiam ser obtidos dali
    • Sobre subprocessos, tenho uma curiosidade genuína sobre como [[ $cmdline ]] && exec {cmdline}>&- e exec {cmdline}< "$dir"/cmdline || continue funcionam
  • Em 2011, fiz entrevista para uma função de SRE em uma empresa de tecnologia bem grande dos EUA; na época, foi a primeira vez que ouvi o termo SRE
    A empresa estava criando uma alternativa ao MS Office baseada em navegador e, depois da triagem por telefone, eu precisava programar em tempo real conversando com o entrevistador dentro do editor de documentos da própria empresa
    Como eu tinha dado notas altas para shell scripting e Linux na autoavaliação, recebi a tarefa de criar um substituto para netstat em Bash, mas na época eu não sabia onde nem como as informações de sockets ficavam em /proc/, então rapidamente concluí que não conseguiria
    Em vez disso, propus criar versões reduzidas de ps e fuser, e a solução que apresentei naquele terrível processador de texto baseado em navegador foi aceita, me levando até a entrevista presencial
    Pensando agora, talvez o cenário hipotético que motivava esse exercício estivesse mais enraizado na realidade do que eu imaginava

    • É bem provável que alguns desses utilitários de sistema, de qualquer forma, olhem internamente para procfs/sysfs
      Eu também começaria por aí
  • Há algum tempo criei, por diversão, um site interativo para explorar a situação de estar conectado por SSH e não conseguir criar novos processos: https://oops.cmdchallenge.com

    • "echo *" não lista todos os arquivos do diretório
      É preciso usar "echo .* *"
    • É legal, mas depois de concluir ele voltou para a primeira etapa e não consegui ver as outras, o que foi frustrante
      Eu queria olhar a lista de "View Solutions" das outras etapas para ver que outras abordagens eram possíveis
  • Izabera é um dos especialistas de #bash@libera
    Desde os tempos do antigo freenode, aprendi muita coisa com esse tipo de especialista ao longo dos últimos 10 anos

  • Isto é um Bash bem limpo
    Pela minha experiência, código Bash costuma ser mal escrito e ineficiente, mas este parece ser um bom exemplo do contrário

    • Para ser Bash limpo, também deveria ser portável; este script é exclusivo para Linux e vai quebrar feio em outros lugares
  • E se você estiver em um shell POSIX confiável que não tem suporte a Bash?
    Este script Bash não é compatível com POSIX

  • Este script não funciona no Bash 3.2, mas funciona no Bash 4.2
    No Bash 3.2, ocorre o erro printf: '(': invalid format character; o ambiente de exemplo é bash-3.2-33.el5_11.4.0.1

    • Acho bastante razoável não oferecer suporte a uma série de releases do Bash de 18 anos atrás e a uma série de releases de sistema operacional de 17 anos atrás
  • Um uso melhor talvez seja ver a lista de processos em um sistema onde procps não está instalado
    Bacana

  • Também dá para criar listeners e clientes em Bash
    Não recomendo para uso real