Olá pessoal. Esta é uma tradução do RedHat RHCE Exam Preparation Book. Na minha opinião, é muito acessível sobre o básico do bash.
Os scripts de shell são uma ciência em si. Sem entrar em detalhes de tudo o que acontece "oculto", você aprenderá como usar os elementos básicos para escrever seus próprios scripts e analisar o que acontece nos scripts de shell de terceiros.

Compreendendo os elementos básicos dos scripts de shell
De fato, um shell script é uma lista de comandos executados seqüencialmente, além de alguma lógica que permite que o código seja executado apenas sob determinadas condições.
Para entender scripts shell complexos, é recomendável que você comece com scripts básicos.
O seguinte é um script muito simples:
Ele contém vários elementos que devem ser usados em todos os scripts. Para iniciantes, há shebang - esta é a linha #! / Bin / bash. Quando o script é iniciado a partir do shell pai, ele abre um subshell no qual os comandos especificados no script são executados.
Esses comandos podem ser interpretados de várias maneiras. Para entender exatamente como eles devem ser interpretados, o shebang é usado. No exemplo acima, shebang deixa claro que o script deve ser executado pelo shell bash.
Outras conchas também podem ser indicadas. Por exemplo, se seu script contiver código Perl, shebang deve ser #! / Usr / bin / perl. Iniciar um script com shebang é uma boa prática; se omitido, o código do script será executado pelo mesmo shell usado para executar o script.
Imediatamente após o shebang, há uma parte explicando sobre o que é o script. Algumas linhas de comentário no início de cada cenário são uma boa ideia. Em um script curto, muitas vezes é óbvio o que ele faz, mas, à medida que o script fica mais longo e à medida que mais pessoas se envolvem em escrevê-lo e apoiá-lo, fica menos claro o que os autores pretendem fazer.
Para evitar essa situação, adicione linhas de comentário começando com cada caractere #. Os comentários podem estar não apenas nas primeiras linhas, mas também no início de cada subseção do script. Isso certamente ajudará se você ler seu script em alguns meses!
Você também pode comentar não apenas em subseções, mas também em linhas individuais.
Independentemente da posição em que é usado, tudo, desde o caractere # até o final da linha, é um comentário.
Após o bloco de comentários, o corpo do script está localizado. No exemplo acima, esses são vários comandos que são executados seqüencialmente. O corpo do script de shell pode aumentar à medida que se desenvolve.
No final do script, incluí a instrução 
exit 0 . A instrução exit informa ao shell pai se o script foi bem-sucedido. O estado de saída do último comando no script é o estado de saída do próprio script, a menos que a 
saída 0 seja usada no final do script.
É útil saber que você pode trabalhar com 
exit para informar ao shell pai como foram as coisas.
Introduzido no shell pai, o echo $? permite consultar o status de saída do último script em execução.
Após criar o script, verifique se ele pode ser executado. A maneira mais comum de fazer isso é aplicar um pouco de execução a ele. Portanto, se o nome do arquivo de script for hello, use o 
comando chmod + x ./hello para torná-lo executável.
O script também pode ser executado como um argumento para o comando bash. Nesse caso, digite 
bash ./hello para executar o script hello. Se o script for executado como um argumento para o comando bash, o arquivo de script não precisará ser executável.
De fato, você pode armazenar o script em qualquer lugar, mas se você quiser armazená-lo em um diretório que não esteja incluído na variável $ PATH, será necessário executá-lo com ./ na frente do nome do script.
Digite 
./hello para executar o script ou coloque-o no diretório padrão incluído na variável $ PATH, por exemplo, / usr / local / bin.
Você também pode colocar o script no diretório / bin, após o qual basta digitar o nome do arquivo em qualquer lugar do sistema de arquivos e o script será executado.
ExemploUsando 
vi / bin / datetime, crie um arquivo chamado datetime no diretório / bin. Cole este conteúdo no arquivo criado:
 
Depois de salvar o arquivo, digite 
chmod + x / bin / datetime para dar permissão ao arquivo para executar. Por exemplo, mude para o diretório inicial usando o 
comando cd ~ e digite simplesmente 
datetime .
Vá, por exemplo, para o diretório inicial do cd ~ e insira datetime.
 [root@localhost ~] 
Usando variáveis e entradas
Os scripts bash são muito mais do que apenas uma lista de comandos executados sequencialmente. Uma das coisas boas sobre scripts é que eles podem trabalhar com variáveis e entradas para tornar o script flexível. Nesta seção, você aprenderá como trabalhar com eles.
Usando parâmetros posicionais
Ao executar o script, você pode usar os argumentos. Um argumento é tudo o que você coloca atrás de um comando de script. Argumentos podem ser usados para tornar o script mais flexível. Pegue o comando 
useradd lisa . Neste exemplo, o comando é 
useradd e seu argumento, 
lisa , indica o que precisa ser feito.
Como resultado desse comando, um usuário chamado lisa deve ser criado.
No script, o primeiro argumento é 
$ 1 , o segundo é 
$ 2. A Listagem 1 mostra como os argumentos podem ser usados. Tente executar esse código especificando nomes de usuários como parâmetros.
Listagem 1 
Parâmetros significam entrada de dados antes de executar o script. Nesse caso, especifiquei 
lisa , 
lori e 
bob como parâmetros após o argumento script name:
 [root@server1 ~] 
Se você tentou executar o código de amostra, poderá notar que seu conteúdo não é perfeito. Se você usar três argumentos ao executar o script da Lista 1, ele funcionará perfeitamente. Se você usar apenas dois argumentos, o terceiro será gerado sem o valor $ 3.
Se você usar quatro argumentos, o quarto valor (que será armazenado em US $ 4) nunca será exibido. Portanto, se você quiser usar argumentos, é melhor usar uma abordagem mais flexível.
Listagem 2 
A Listagem 2 mostra dois novos elementos relacionados aos argumentos:- $ # É um contador que mostra quantos argumentos foram usados ao executar o script.
- $ @ É uma lista de todos os argumentos que foram usados ao executar o script.
Para listar os argumentos que foram usados ao executar esse script, o loop for é usado. Nos loops 
for , as instruções são executadas desde que a condição seja verdadeira. Nesse cenário, a condição 
para i em $ @ significa "para cada argumento". Cada vez que o script passa pelo loop, o valor da variável 
$ @ é atribuído à variável 
$ i .
Portanto, desde que haja argumentos, o corpo do script é executado.
O corpo do loop for sempre começa com 
do e fecha 
done , e os comandos a serem executados são listados entre essas duas palavras-chave. Portanto, o script de exemplo usará 
eco para exibir o valor de cada argumento e parar quando não houver mais argumentos disponíveis.
Vamos tentar o script na Listagem 2 neste exemplo:- Digite vi argumento para criar o arquivo de argumento e copie o conteúdo do script na Listagem 2 para este arquivo.
- Salve o arquivo e torne-o executável.
- Execute o comando ./argument abc . Você verá que três linhas são exibidas.
- Execute o comando ./argument abcdef . Você verá que, além de abc, de f também será exibido.
Variáveis
Uma variável é um rótulo usado para indicar um local específico na memória que contém um valor específico. As variáveis podem ser definidas estaticamente usando NAME = value ou dinamicamente. Existem duas soluções para definir dinamicamente uma variável:
- Use a palavra-chave read em um script para solicitar dados do usuário que está executando o script.
- Use substituição de comando para usar o resultado do comando e atribuí-lo a uma variável. Por exemplo, a data do comando +% d-% m-% y mostra a data atual no formato dia-mês-ano. Para fazer isso em um script, você pode usar HOJE = $ (data +% d-% m-% y) . Para substituir comandos, basta colocar o comando cujo resultado você deseja usar entre os colchetes.
Na seção anterior sobre parâmetros posicionais, você aprendeu como atribuir argumentos a variáveis ao executar um script. Em alguns casos, pode ser mais eficiente solicitar informações quando você achar que algo substancial está faltando. O script abaixo mostra como fazer isso.
Listagem 3. Script de amostra usando o comando 
read 
No script da Listagem 3, o operador 
if ... then ... else ... fi é usado para testar a existência do argumento 
$ 1 . Isso é feito usando 
test (test é um comando separado). O comando test pode ser escrito de duas maneiras *: 
test ou 
[...] . No exemplo, a linha 
se [-z $ 1] ... é executada para ver o teste (marque) 
-z $ 1 .
* 
- na verdade, três fontes (aprox. Tradutor)O teste -z verifica se 
$ 1 existe ou não. Em outras palavras, a linha 
se [-z $ 1] verifica se 
$ 1 está vazio, o que significa que nenhum argumento foi fornecido quando esse script foi executado. Nesse caso, os comandos após a instrução 
then são executados.
Observe que, ao escrever o comando de 
teste com colchetes, é importante usar espaços após o colchete de abertura e antes do colchete de fechamento, sem espaços, o comando não funcionará.
Observe que a instrução 
then segue imediatamente o 
teste . Isso é possível porque um ponto-e-vírgula (;) é usado. O ponto e vírgula é um separador de comandos e pode substituir uma nova linha em um script.
A instrução 
then executa dois comandos: o comando 
echo , que exibe a mensagem na tela, e o comando 
read .
O comando 
read para o script para que a entrada do usuário possa ser processada e armazenada na variável TEXT. Portanto, 
ler TEXT coloca toda a entrada do usuário na variável TEXT, que será usada posteriormente no script.
A próxima parte é representada pela 
instrução else . Os comandos após a 
instrução else são executados em todos os outros casos, o que nesse caso significa "caso contrário, se o argumento foi fornecido". Nesse caso, a variável TEXT é determinada e o valor atual de 
$ 1 é atribuído a ela.
Observe como a variável é definida: imediatamente após o nome da variável, existe um sinal = seguido de $ 1. Observe que você nunca deve usar espaços ao definir variáveis.
Então, as condições if são fechadas usando o operador 
fi . Após a conclusão da condição if, você tem certeza de que a variável TEXT está definida e possui um valor. A penúltima linha do script lê o valor da variável TEXT e mapeia esse valor para STDOUT usando o comando 
echo . Observe que, para solicitar o valor atual de uma variável, ele se refere ao nome da variável, começando com o sinal $ à frente.
Você pode praticar usando este exemplo ao trabalhar com entrada.- Abra o editor e crie um arquivo chamado texto. Digite o conteúdo do código na Listagem 3 neste arquivo.
- Escreva o arquivo no disco e execute chmod + x text para torná-lo executável.
- Execute o script executando ./text e sem argumentos adicionais. Você verá que ele pede entrada.
- Execute o script usando " hello " como argumento (./text hello). O resultado exibirá "você inseriu o texto hello" em STDOUT.
Usando condições e loops
Como você já viu, instruções condicionais podem ser usadas em um script. Essas instruções condicionais são executadas apenas se uma determinada condição for atendida.
Existem várias instruções e loops condicionais no bash que são frequentemente usados.
- if ... then ... else - usado para executar código se uma determinada condição for atendida
- for - usado para executar comandos para um intervalo de valores
- while - usado para executar código se uma determinada condição for atendida
- before - usado para executar o código até que uma determinada condição seja atendida
- case - usado para avaliar um número limitado de valores específicos
se então mais
A 
construção if then else é comum para avaliar condições específicas. Você já viu um exemplo com ele. Essa declaração condicional é frequentemente usada com o comando 
test . Este comando permite verificar muitas coisas: por exemplo, não apenas se um arquivo existe, mas também comparar arquivos, comparar números inteiros e muito mais.
Você pode aprender mais sobre teste na referência com o comando man test.
O básico 
se construir é 
se ... então ... fi .
Ele compara uma condição, conforme mostrado no exemplo a seguir:
 if [ -z $1 ] then echo no value provided fi 
Na Listagem 3, você viu como pode avaliar duas condições, incluindo 
outras em uma expressão. A Listagem 4 mostra como avaliar várias condições de 
se para 
outro . Isso é útil se você precisar verificar muitos valores diferentes.
Observe que este exemplo também usa vários comandos de 
teste .
Listagem 4 . Exemplo com 
if then else 
|| e &&
Em vez de escrever 
instruções completas 
if ..., você pode usar os operadores lógicos 
|| bem como 
&& . 
|| é um "OR" lógico e executará a segunda parte da instrução somente se a primeira parte não for verdadeira; 
&& é um "AND" lógico e executará a segunda parte da declaração somente se a primeira parte for verdadeira.
Considere estas duas linhas: [ -z $1 ] && echo no argument provided 
 ping -c 1 8.8.8.8 2>/dev/null || echo node is not available 
O primeiro exemplo verifica se 
$ 1 está vazio. Se esta verificação estiver correta (o que basicamente significa que o comando termina com o código de saída 0), o segundo comando é executado.
No segundo exemplo, o comando 
ping é usado para verificar a disponibilidade do host.
Este exemplo usa um "OR" lógico para exibir o texto "o nó não está disponível" no caso de uma falha no comando 
ping .
Você encontrará isso frequentemente, em vez da 
instrução if condicional, 
&& e 
|| . No exercício abaixo, você pode praticar o uso de instruções condicionais usando 
if ... then ... else , ou 
&& e 
|| .
Exercício . Usando 
if ... then ... elseNeste exercício, você trabalhará em um script que verifica o que é um arquivo e o que é um diretório.
- Inicie o editor e crie um script chamado filechk.
- Copie o conteúdo da Listagem 4 neste script.
- Execute alguns testes com ele, como ./filechk / etc / hosts , ./filechck / usr , ./filechk arquivo não existente .
For loop
O loop for é uma ótima solução para o processamento de intervalos de dados. Na Listagem 5, você pode ver o primeiro exemplo com 
for , onde o intervalo é determinado e processado enquanto houver valores brutos nesse intervalo.
Listagem 5 
Um loop 
for sempre começa com a palavra-chave for, seguida por uma condição que precisa ser verificada. Isso é seguido pela palavra-chave do, seguida pelos comandos que devem ser executados; se a condição for verdadeira, o loop será finalizado usando a palavra 
- chave 
done .
No exemplo da Listagem 5, é possível ver que a condição é um intervalo de números entre parênteses designados à variável COUNTER.
Uma pequena explicaçãoAs expressões aritméticas internas 
((...)) são calculadas e seu resultado é retornado. Por exemplo, no caso mais simples, a construção a = $ ((5 + 3)) atribuirá à variável "a" o valor da expressão "5 + 3" ou 8. Além disso, parênteses duplos permitem trabalhar com variáveis no estilo da linguagem C.
Primeiro, a variável é inicializada para 100 e, desde que o valor seja maior que 1, é subtraído 1. A cada iteração, desde que a condição seja verdadeira, o valor da variável $ COUNTER é exibido usando o comando 
echo .
Na Listagem 6, você pode ver uma das minhas frases favoritas com 
for . O intervalo é definido desta vez como uma sequência de números, começando de 100 e chegando a 104.
Listagem 6 for i in {100..104}; do ping –c 1 192.168.4.$i >/dev/null && echo 192.168.4.$i is up; done 
Observe como o intervalo é determinado: primeiro você especifica o primeiro número, depois dois pontos e indica o último número no intervalo. Além disso, com 
for i in, para cada um desses números, a variável 
i é atribuída. Cada um desses números é atribuído à variável 
ie o comando 
ping é executado, em que a opção 
-c 1 garante que apenas uma solicitação seja enviada.
O resultado do comando 
ping não 
é levado em consideração, portanto sua saída é redirecionada para / dev / null. Com base no status de saída do comando 
ping , uma parte da expressão 
&& é executada. Portanto, se o host estiver disponível, uma linha será exibida indicando que está em execução.
Entendendo enquanto e até
Se a instrução for que você acabou de ler for útil para trabalhar com intervalos de elementos, a instrução while será útil quando você desejar rastrear algo como acessibilidade do processo. Há também uma instrução 
até , que é executada desde que a condição sendo verificada seja falsa. Na Listagem 7, você pode ler como 
while é usado para monitorar a atividade do processo.
Nota Eu não entendi o que esse script faz. No meu caso, o CentOS 7 é usado e, por padrão, não há monitor, embora o script diga explicitamente:  uso: monitor <nome do processo> 
Em algum lugar por meia hora, pesquisei no Google o programa de monitoramento do CetOS, mas não o encontrei. E geralmente não está claro qual monitor lateral está aqui se o ps aux for usado. De qualquer forma, não entendi o que esse script faz. Uma grande solicitação para ajudar a resolver esse problema é ajustar o texto e / ou script.
Listagem 7 
O script na Listagem 7 consiste em duas partes. Primeiro, há um 
loop while . Em segundo lugar, há tudo o que precisa ser feito quando o 
loop while não 
é mais avaliado como verdadeiro.
O núcleo do 
loop while é o comando 
ps , que tem um valor de 
$ 1 .
Observe o uso de 
grep -v grep , que exclui as linhas que contêm o 
comando grep do resultado. Lembre-se de que o comando 
ps incluirá todos os processos em execução, incluindo o 
comando grep , para os quais a saída do 
comando ps é passada. Isso pode levar a uma correspondência positiva falsa.
A saída do comando 
ps aux é redirecionada para / dev / tty11. Isso permite que você leia os resultados de tty11 posteriormente, se necessário, mas eles não são exibidos por padrão.
while , , . 
sleep 5 , 5 .
while , . ( , ), , .
, . 
mail -s “process $1 has stopped” root < . root , Linux*. 
mail , 
-s .
* — CentOS . (. )< . .
mail , . , , . STDIN. - .
while — 
until , 8. 
until , , .
8 
users $1 , . , . , , 
until .
8 
case
— 
case *. 
case . , 
case Linux, .
* — ?case , , , .
9 
case , .
9 case "$1" in start) start;; stop) rm -f $lockfile stop;; restart) restart;; reload) reload;; status) status ;; *) echo "Usage: $0 (start|stop|restart|reload|status)" ;; esac 
O gabinete possui vários recursos. Primeiro vem a linha - caso em sequência . Isto é seguido por uma lista de todos os valores possíveis que precisam ser avaliados. Cada elemento é fechado com um colchete ) .Isto é seguido por uma lista de comandos a serem executados se um argumento específico foi usado. A lista de comandos é fechada com ponto e vírgula duplo ;; pode ser usado imediatamente após o último comando e pode ser usado em uma linha separada.Observe também que *) se aplica a todos os outros parâmetros não especificados anteriormente. Este é um operador abrangente.O loop de iteração do caso termina com a instrução esac .Observe que as seqüências no caso são executadas em ordem. Quando a primeira correspondência é feita, a declaração do caso não avalia nada.Como parte da avaliação, modelos semelhantes ao modelo podem ser usados. Isso é mostrado em *) uma sequência que corresponde a tudo. Mas você também pode usar sequências como start | Start | START) para combinar com outro caso .Depurando scripts no Bash
, , . , 
bash -x . , , , .
10 
bash -x , , 
grep , , .
 [root@server1 ~] 
, . , .