Sobre interfaces e a verificação de comandos necessários no bash

9 min

language: ja bn en es hi pt ru zh-cn zh-tw

Olá, sou um incompetente.
Terminei meu último dia de trabalho, recebi chocolates de uma colega de trabalho, fui levado para comer yakiniku um pouco antes de me aposentar, e me diverti conversando com uma pessoa que trabalhou com redes por 25 anos sobre o ambiente de rede doméstico dela no passado e no presente, e eu sobre o meu ambiente de servidor doméstico.
Sinto que consegui fazer o que estava ao meu alcance, por mais imaturo que eu seja, mas como sou uma pessoa com muitas falhas, sinto-me um pouco arrependido.


Sinto diariamente que os scripts de shell são extremamente poderosos.
Claro, a baixa portabilidade é um problema inegável, como a incapacidade de escrever funções como no csh, o shell padrão do FreeBSD atualmente.
No entanto, acredito que a verdadeira força dos scripts de shell reside na facilidade de manipulação de interfaces.

Interfaces de C e scripts de shell

Por exemplo, digamos que você use echo em um script de shell da seguinte forma:

echo "test"

Isso corresponde à saída padrão em C.

#include <stdio.h>

int main() {
    const char *message = "test";

    // Imprime a mensagem na saída padrão
    fprintf(stdout, "%s\n", message);

    return 0;
}

Se você quiser imprimir na saída de erro padrão, faria um redirecionamento da seguinte forma:

echo "testerr" 1>&2

E, no caso da linguagem C, corresponde ao seguinte:

#include <stdio.h>

int main() {
    const char *message = "testerr";

    // Imprime a mensagem na saída de erro padrão
    fprintf(stderr, "%s\n", message);

    return 0;
}

Além disso, a maioria das falhas na execução de comandos em GNU/Linux tem valores de retorno engenhosamente projetados graças aos pioneiros do passado, tornando fácil testar condições e bastante eficaz se tratado como uma linguagem de script.
No entanto, o problema é que isso só beneficia em ambientes onde scripts de shell podem ser usados.
Mesmo que um código semelhante seja escrito em outras linguagens, sua versatilidade se aplica, mas há partes onde os comandos funcionam como o que seria uma biblioteca em uma linguagem, e sinto que esse é o motivo pelo qual se diz que a versatilidade é limitada.
No entanto, a capacidade de manipular descritores de arquivo de forma tão simplificada é algo que considero extremamente poderoso.

Para else, basta conectar dois pipes. ※Pensei nisso depois de escrever, mas, estritamente falando, não é um else ^^;
É apenas um comportamento semelhante a um else quando o valor de retorno não é 0.

$ curl aa || echo "wtf"
curl: (6) Could not resolve host: aa
wtf

Como teria sido bom se eu soubesse de algo tão útil quando era estudante do ensino médio.
Gostaria que mais sites oferecessem oportunidades para aprender scripts de shell.

Na verdade, agora que penso nisso, lembro que o ambiente japonês do GNU/Linux na época era bastante difícil, e a previsão de entrada de texto em japonês não era prática, então talvez a facilidade de hoje se deva à popularização do Chrome OS, que fez com que a entrada de texto em japonês OSS prosperasse.
Lembro-me também de ter configurado um ThinkPad com Ubuntu para um amigo excêntrico que o queria quando éramos estudantes do ensino médio...

Então, como verificar os comandos?

Eu estava pensando se haveria uma maneira inteligente e fácil de ler para escrever a verificação de comandos em um script Bash.

Dito isso, é claro que é conveniente passar os comandos de um array para um loop for, o que já é inteligente, mas ao olhar a forma como o array é preenchido...

#!/bin/bash
cmds=(aa bb cc)
for i in ${cmds[@]}; do
  command -v $i 1> /dev/null || echo "Please install $i"
done

Os comandos são armazenados em cmds como um array usando (), e o array é expandido com ${cmds[@]}.
No entanto, se o número de comandos aumentar e você continuar adicionando-os a cmds=(), você começa a se perguntar se realmente precisa escrevê-los aqui.
Em outras linguagens, as informações de dependência estão contidas em arquivos como Cargo.toml, deno.json, go.mod, Gemfile, e o frequentemente odiado requirements.txt.
Seria conveniente ter um arquivo que agrupasse tudo dessa forma.

Então, tentei fazer algo assim:

#!/bin/bash
cat ./cmd | xargs which 1> /dev/null || echo "Please install cmd"

E como seria o arquivo cmd?

$ cat cmd
ls
pwd
cargo

Na verdade, eu queria verificar com o comando command, mas command funciona como um comando interno do shell e não pôde ser passado para xargs.

$ which command
which: no command in (/home/haturatu/.rbenv/bin:/home/haturatu/.rbenv/shims:/home/haturatu/.deno/bin:/home/haturatu/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/opt/android-sdk/platform-tools:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/usr/lib/plan9/bin:/home/haturatu/.local/bin:/home/haturatu/.local/bin:/home/haturatu/Android/Sdk/cmdline-tools/tools/bin:/home/haturatu/Android/Sdk/platform-tools:/home/haturatu/Android/Sdk/emulator:/home/haturatu/Android/Sdk/tools:/home/haturatu/Android/Sdk/tools/bin:/home/haturatu/Android/Sdk/cmdline-tools/tools/bin:/home/haturatu/Android/Sdk/platform-tools:/home/haturatu/Android/Sdk/emulator:/home/haturatu/Android/Sdk/tools:/home/haturatu/Android/Sdk/tools/bin:/home/haturatu/.npm-global/bin:/home/haturatu/go/bin)

Peço desculpas se estiver enganado, mas quando passado para xargs, ele provavelmente não é reconhecido porque xargs opera como um processo separado do processo bash que o executou.
Portanto, não é possível passar o comando que falhou com which para a mensagem Please install cmd, mas como a saída de erro de which já aparece antes disso, achei que não seria necessário.
※Pensei nisso depois de escrever, mas talvez xargs /bin/bash command -v funcione...

Há mais uma vantagem em colocar esse grupo de comandos em um arquivo separado.
Você pode instalá-los todos de uma vez a partir deste arquivo.

cat cmd | xargs -I {} sudo pacman -S --noconfirm {}

No caso do apt, é possível fazer o mesmo com a opção -y.


Então, independentemente de eu realmente usar isso ou não, vou deixá-lo como uma ideia.
Até a próxima. Conto com vocês. (É apenas uma impressão minha, ou percebi que escrevi vários artigos desde o artigo de encerramento do ano?)

Related Posts