Uma shell é o interpretador de comandos para o sistema operacional. Bash é meu shell favorito, mas todo shell Linux interpreta os comandos digitados pelo usuário ou administrador de sistema em uma forma que o sistema operacional pode usar. Quando os resultados são retornados ao programa shell, ele os envia para STDOUT que, por padrão, os exibe no terminal. Todas as shells com as quais estou familiarizado são também linguagens de programação.

Características como preenchimento de tabulação, chamada e edição de linha de comando e atalhos como aliases contribuem para o seu valor como uma poderosa shell. Seu modo de edição de linha de comando padrão usa Emacs, mas uma das minhas características favoritas do Bash é que eu posso mudá-lo para o modo Vi para usar comandos de edição que já fazem parte da minha memória muscular.

No entanto, se você pensar no Bash apenas como uma shell, você perde muito do seu verdadeiro poder. Enquanto pesquisava o meu curso de auto-estudo de três volumes do Linux (no qual esta série de artigos é baseada), aprendi coisas sobre o Bash que nunca tinha conhecido em mais de 20 anos de trabalho com o Linux. Alguns destes novos conhecimentos estão relacionados com o seu uso como linguagem de programação. O Bash é uma poderosa linguagem de programação, perfeitamente projetada para uso na linha de comando e em scripts shell.

Esta série de três partes explora o uso do Bash como uma linguagem de programação de interface de linha de comando (CLI). Este primeiro artigo aborda alguma programação simples de linha de comando com Bash, variáveis e operadores de controle. Os outros artigos exploram tipos de arquivos Bash; operadores lógicos string, numéricos e diversos que fornecem lógica de controle de execução-fluxo; diferentes tipos de expansões de shell; e o for, while e até loops que permitem operações repetitivas. Eles também irão olhar para alguns comandos que simplificam e suportam o uso dessas ferramentas.

A shell

Uma shell é o interpretador de comandos para o sistema operacional. Bash é meu shell favorito, mas todo shell Linux interpreta os comandos digitados pelo usuário ou administrador de sistema em uma forma que o sistema operacional pode usar. Quando os resultados são retornados para o programa shell, ele os exibe no terminal. Todos os shells com os quais estou familiarizado são também linguagens de programação.

Bash significa Bourne Again Shell porque o Bash shell é baseado no antigo Bourne shell que foi escrito por Steven Bourne em 1977. Muitos outros shells estão disponíveis, mas estes são os quatro que encontro com mais frequência:

  • csh: A shell C para programadores que gostam da sintaxe da linguagem C
  • ksh: O shell Korn, escrito por David Korn e popular entre os utilizadores de Unix
  • tcsh: Uma versão do csh com características mais fáceis de usar
  • zsh: O Z shell, que combina muitas características de outros shells populares

Todos os shells têm comandos embutidos que suplementam ou substituem os fornecidos pelos utilitários do núcleo. Abra a página de manual do shell e encontre a secção “BUILT-INS” para ver os comandos que fornece.

Cada shell tem a sua própria personalidade e sintaxe. Alguns funcionarão melhor para si do que outros. Eu usei a shell C, a shell Korn, e a shell Z. Eu ainda gosto do Bash shell mais do que qualquer um deles. Use a que funciona melhor para você, embora isso possa exigir que você tente algumas das outras. Felizmente, é bastante fácil mudar os shells.

Todos estes shells são linguagens de programação, assim como intérpretes de comandos. Aqui está uma visita rápida a algumas construções e ferramentas de programação que são parte integrante do Bash.

Bash como uma linguagem de programação

A maioria dos sysadmins tem usado o Bash para emitir comandos que são normalmente bastante simples e directos. Mas o Bash pode ir além da entrada de comandos simples, e muitos sysadmins criam programas de linha de comando simples para executar uma série de tarefas. Estes programas são ferramentas comuns que podem poupar tempo e esforço.

O meu objectivo ao escrever programas CLI é poupar tempo e esforço (ou seja, ser o administrador de sistema preguiçoso). Os programas CLI suportam isso listando vários comandos em uma seqüência específica que executam um após o outro, assim você não precisa observar o progresso de um comando e digitar o próximo comando quando o primeiro terminar. Você pode ir fazer outras coisas e não precisa monitorar continuamente o progresso de cada comando.

O que é “um programa”?

O Dicionário de Computação On-line Livre (FOLDOC) define um programa como: “As instruções executadas por um computador, ao contrário do dispositivo físico em que são executadas.” O WordNet da Princeton University define um programa como: “As instruções executadas por um computador, ao contrário do dispositivo físico no qual elas rodam”: “…uma sequência de instruções que um computador pode interpretar e executar…” A Wikipédia também tem uma boa entrada sobre programas de computador.

Por isso, um programa pode consistir em uma ou mais instruções que executam uma tarefa específica e relacionada. Uma instrução de programa de computador também é chamada de instrução de programa. Para sysadmins, um programa é normalmente uma sequência de comandos shell. Todos os shells disponíveis para Linux, pelo menos os que eu estou familiarizado, têm pelo menos uma forma básica de capacidade de programação, e Bash, o shell padrão para a maioria das distribuições Linux, não é exceção.

Embora esta série use Bash (por ser tão onipresente), se você usar um shell diferente, os conceitos gerais de programação serão os mesmos, embora as construções e sintaxe possam diferir um pouco. Alguns shells podem suportar algumas funcionalidades que outros não suportam, mas todos eles fornecem alguma capacidade de programação. Os programas shell podem ser armazenados em um arquivo para uso repetido, ou podem ser criados na linha de comando conforme necessário.

Programas CLI simples

Os programas de linha de comando mais simples são uma ou duas declarações de programa consecutivas, que podem estar relacionadas ou não, que são inseridas na linha de comando antes que a tecla Enter seja pressionada. A segunda instrução em um programa, se houver uma, pode depender das ações da primeira, mas não precisa ser.

Tem também um pouco de pontuação sintática que precisa ser claramente indicada. Ao digitar um único comando na linha de comando, pressionar a tecla Enter encerra o comando com um ponto-e-vírgula implícito (;). Quando usado em um programa de shell CLI inserido como uma única linha na linha de comando, o ponto-e-vírgula deve ser usado para terminar cada instrução e separá-la da próxima. A última instrução em um programa shell CLI pode usar um ponto-e-vírgula explícito ou implícito.

Some sintaxe básica

Os exemplos a seguir esclarecerão essa sintaxe. Este programa consiste de um único comando com um terminador explícito:

$ echo "Hello world." ;
Hello world.

Isso pode não parecer muito de um programa, mas é o primeiro programa que eu encontro com cada nova linguagem de programação que aprendo. A sintaxe pode ser um pouco diferente para cada linguagem, mas o resultado é o mesmo.

Vamos expandir um pouco neste programa trivial mas ubíquo. Seus resultados serão diferentes dos meus porque eu fiz outros experimentos, enquanto você pode ter apenas os diretórios e arquivos padrão que são criados no diretório home da conta na primeira vez que você entrar em uma conta através do GUI desktop.

$ echo "My home directory." ; ls ;
My home directory.
chapter25 TestFile1.Linux dmesg2.txt Downloads newfile.txt softlink1 testdir6
chapter26 TestFile1.mac dmesg3.txt file005 Pictures Templates testdir
TestFile1 Desktop dmesg.txt link3 Public testdir Videos
TestFile1.dos dmesg1.txt Documents Music random.txt testdir1

Isso faz um pouco mais de sentido. Os resultados são relacionados, mas as instruções individuais do programa são independentes umas das outras. Note que eu gosto de colocar espaços antes e depois do ponto-e-vírgula porque isso torna o código um pouco mais fácil de ler. Tente aquele pequeno programa CLI novamente sem um ponto-e-vírgula explícito no final:

$ echo "My home directory." ; ls 

Não há diferença na saída.

Algo sobre variáveis

Como todas as linguagens de programação, a shell Bash pode lidar com variáveis. Uma variável é um nome simbólico que se refere a um local específico na memória que contém um valor de algum tipo. O valor de uma variável é mutável, ou seja, é variável.

Bash não digita variáveis como C e linguagens relacionadas, definindo-as como inteiros, pontos flutuantes, ou tipos de string. Em Bash, todas as variáveis são strings. Uma string que é um número inteiro pode ser usada na aritmética de números inteiros, que é o único tipo de matemática que o Bash é capaz de fazer. Se matemática mais complexa for necessária, o comando bc pode ser usado em programas e scripts CLI.

Variáveis são valores atribuídos e podem ser usados para se referir a esses valores em programas e scripts CLI. O valor de uma variável é definido usando seu nome, mas não precedido por um sinal $. A atribuição VAR=10 define o valor da variável VAR como 10. Para imprimir o valor da variável, é possível utilizar a instrução echo $VAR. Comece com variáveis de texto (isto é, não-numéricas).

Variáveis de caixa tornam-se parte do ambiente shell até que sejam desajustadas.

Cheque o valor inicial de uma variável que não foi atribuída; deve ser nulo. Em seguida, atribua um valor à variável e imprima-o para verificar seu valor. Você pode fazer tudo isso em um único programa CLI:

$ echo $MyVar ; MyVar="Hello World" ; echo $MyVar ;
Hello World
$

Nota: A sintaxe da atribuição de variáveis é muito estrita. Não deve haver espaços em nenhum dos lados do sinal igual (=) na declaração de atribuição.

A linha vazia indica que o valor inicial de MyVar é nulo. A alteração e definição do valor de uma variável são feitas da mesma maneira. Este exemplo mostra tanto o valor original quanto o novo valor.

Como mencionado, Bash pode realizar cálculos aritméticos inteiros, o que é útil para calcular uma referência para a localização de um elemento em um array ou para fazer problemas matemáticos simples. Ele não é adequado para computação científica ou qualquer coisa que requeira casas decimais, como cálculos financeiros. Existem ferramentas muito melhores para estes tipos de cálculos.

Existe um cálculo simples:

$ Var1="7" ; Var2="9" ; echo "Result = $((Var1*Var2))"
Result = 63

O que acontece quando se executa uma operação matemática que resulta num número de ponto flutuante?

O resultado é o número inteiro mais próximo. Note que o cálculo foi realizado como parte da declaração de eco. A matemática é executada antes do comando de eco envolvente, devido à ordem de precedência do Bash. Para detalhes veja a página de manual do Bash e procure “precedência”

Operadores de controle

Operadores de controle de Shell são um dos operadores sintáticos para facilmente criar alguns programas de linha de comando interessantes. A forma mais simples de programa CLI é apenas encadear vários comandos em uma seqüência na linha de comando:

command1 ; command2 ; command3 ; command4 ; . . . ; etc. ;

Todos estes comandos rodam sem problemas desde que não ocorram erros. Mas o que acontece quando ocorre um erro? Você pode antecipar e permitir a ocorrência de erros usando os operadores de controle de barra embutidos && e || Operadores de controle de barra. Estes dois operadores de controle fornecem algum controle de fluxo e permitem que você altere a seqüência de execução do código. O ponto-e-vírgula também é considerado um operador de controle de Bash, assim como o novo caractere de linha.

O operador && simplesmente diz, “se o comando1 for bem sucedido, então execute o comando2. Se o comando1 falhar por qualquer razão, então o comando2 é pulado”. Essa sintaxe se parece com isto:

command1 && command2

Agora, veja alguns comandos que irão criar um novo diretório e – se for bem sucedido – faça-o o atual diretório de trabalho (PWD). Certifique-se de que seu diretório home (~) é o PWD. Tente isto primeiro em /root, um diretório que você não tem acesso a:

O erro foi emitido pelo comando mkdir. Você não recebeu um erro indicando que o arquivo não pôde ser criado porque a criação do diretório falhou. O operador de controle && sentiu o código de retorno não zero, então o comando de toque foi pulado. Usando o operador de controle && impede que o comando de toque seja executado, pois houve um erro na criação do diretório. Este tipo de controle de fluxo de programa de linha de comando pode evitar que os erros se compliquem e que se crie uma verdadeira bagunça de coisas. Mas é hora de ficar um pouco mais complicado.

O operador de controle || permite adicionar outra instrução do programa que executa quando a instrução inicial do programa retorna um código maior que zero. A sintaxe básica é assim:

command1 || command2 

Esta sintaxe diz: “Se o comando1 falhar, execute o comando2”. Isso implica que se o comando1 for bem sucedido, o comando2 é pulado. Tente isso tentando criar um novo diretório:

Isso é exatamente o que você esperaria. Como o novo diretório não pôde ser criado, o primeiro comando falhou, o que resultou na execução do segundo comando.

Combinar estes dois operadores fornece o melhor de ambos. A sintaxe do operador de controle usando algum controle de fluxo toma esta forma geral quando os operadores de controle && e || são usados:

preceding commands ; command1 && command2 || command3 ; following commands

Esta sintaxe pode ser declarada desta forma: “Se o comando1 sai com um código de retorno 0, então execute o comando2, caso contrário execute o comando3.” Tente:

Tente agora o último comando novamente usando seu diretório home ao invés do diretório /root. Você terá permissão para criar este diretório:

$ Dir=~/testdir ; mkdir $Dir && cd $Dir || echo "$Dir was not created."
$

A sintaxe do operador de controle, como o comando1 && comando2, funciona porque todo comando envia um código de retorno (RC) para a shell que indica se ele completou com sucesso ou se houve algum tipo de falha durante a execução. Por convenção, um RC de zero (0) indica sucesso, e qualquer número positivo indica algum tipo de falha. Algumas das ferramentas do sysadmins utilizam apenas um (1) para indicar uma falha, mas muitas utilizam outros códigos para indicar o tipo de falha que ocorreu.

A variável da shell do Bash $? contém o RC do último comando. Este RC pode ser verificado muito facilmente por um script, o próximo comando de uma lista de comandos, ou mesmo o administrador de sistema diretamente. Comece executando um simples comando e imediatamente verificando o RC. O RC será sempre para o último comando que rodou antes de você olhar para ele.

O RC, neste caso, é zero, o que significa que o comando foi completado com sucesso. Agora tente o mesmo comando no diretório home do root, um diretório que você não tem permissões para:

Neste caso, o RC é dois; isto significa que a permissão foi negada para um usuário não root acessar um diretório para o qual o usuário não tem permissão de acesso. Os operadores de controle usam esses RCs para permitir que você altere a seqüência de execução do programa.

Resumo

Este artigo olhou para o Bash como uma linguagem de programação e explorou sua sintaxe básica, bem como algumas ferramentas básicas. Ele mostrou como imprimir dados para STDOUT e como usar variáveis e operadores de controle. O próximo artigo desta série analisa alguns dos muitos operadores lógicos do Bash que controlam o fluxo de execução das instruções.

Deixe uma resposta

O seu endereço de email não será publicado.