- Aprender
- Computação e TI
- TI, redes e nuvem
- Fundamentos de Linux
- Scripts de shell
Fundamentos de scripts de shell
BásicoAula 4 de 7 do curso Curso de Fundamentos de Linux
O que você vai aprender
- Transformar uma sequência de comandos que você digita repetidamente em um arquivo de script, iniciá-lo com a linha correta do interpretador e executá-lo a partir de qualquer diretório.
- Transformar comandos repetidos em um arquivo de scriptEscrever comandos em ordem em um arquivo de texto simples, adicionar comentários e iniciar o arquivo com uma linha shebang que indique o Bash como interpretador.
- Executar um script e escolher onde armazená-loTornar um script executável, executá-lo pelo caminho ou por meio de um interpretador, colocá-lo em um diretório no PATH e saber quando um script pode alterar seu shell atual.
- Transformar comandos repetidos em um arquivo de script
- Guardar textos, números e saídas de comandos em variáveis, ler entradas do usuário e usar aspas para que espaços e caracteres especiais cheguem aos comandos sem alterações.
- Criar, ler e exportar variáveisAtribuir e usar variáveis do shell, escolher bons nomes, ler entradas do usuário e passar variáveis aos programas iniciados por um script.
- Proteger palavras, variáveis e caracteres especiais com aspas ou escapeEscolher entre aspas simples, aspas duplas e barras invertidas e proteger cada expansão de variável com aspas para que espaços e caracteres curinga nos valores não prejudiquem um comando.
- Capturar a saída de comandos e calcular com números inteirosArmazenar a saída de um comando com substituição de comando e fazer operações com números inteiros, por exemplo para criar nomes de arquivo com datas e manter contadores.
- Criar, ler e exportar variáveis
- Ler e definir o código de saída de comandos e scripts, encadear comandos conforme o sucesso ou a falha e encontrar e interromper erros antes que causem danos.
- Ler e definir códigos de saída e usá-los para encadear comandosUsar o código de saída retornado por cada comando, encerrar um script com um código significativo e executar comandos apenas quando um comando anterior tiver sido bem-sucedido ou falhado.
- Encontrar erros e encerrar um script com segurançaVerificar e rastrear um script para encontrar erros, enviar mensagens de erro para a saída de erro padrão e fazer um script parar em caso de falhas, variáveis não definidas e falhas em encadeamentos.
- Ler e definir códigos de saída e usá-los para encadear comandos
- Testar arquivos, textos e números, escolher o que fazer com if e case e repetir comandos para itens de listas, arquivos e linhas com laços for, while e until.
- Testar arquivos, strings e númerosEscrever condições com test, [ ] e [[ ]] para verificar se arquivos existem, comparar textos e números inteiros e combinar ou negar essas condições.
- Escolher ações com if, elif, else e caseExecutar comandos diferentes conforme uma condição com if, elif e else e comparar um valor com vários padrões usando case.
- Repetir comandos para itens de listas e arquivos com forPercorrer uma lista de palavras, os arquivos que correspondem a um padrão, um intervalo de números ou os argumentos de um script e lidar com nomes de arquivo que contêm espaços.
- Repetir comandos até que uma condição mude com while e untilExecutar comandos enquanto uma condição for bem-sucedida ou até que ela seja, ler um arquivo linha por linha e controlar laços com break, continue e sleep.
- Testar arquivos, strings e números
- Fornecer entradas a um script na linha de comando, ler os argumentos dentro do script, verificá-los e fornecer valores padrão para que o mesmo script funcione em vários casos.
- Ler parâmetros posicionais e a quantidade de argumentosUsar
$0,$1a$9,${10},$#e"$@"para ler as palavras fornecidas após o nome de um script e usarshiftpara percorrê-las. - Verificar argumentos, mostrar instruções de uso e definir valores padrãoValidar a quantidade e o tipo dos argumentos, imprimir uma mensagem de uso e sair com um código de erro, usar valores padrão e tratar opções simples.
- Ler parâmetros posicionais e a quantidade de argumentos
- Executar scripts em horários ou intervalos definidos sem estar conectado, com cron ou temporizadores do systemd, e verificar se as execuções agendadas ocorrem e são bem-sucedidas.
- Agendar tarefas com cronEscrever entradas de crontab com os cinco campos de tempo, editá-las e listá-las com crontab e preparar scripts para o ambiente mínimo do cron.
- Agendar tarefas com temporizadores do systemdAssociar uma unidade de serviço a uma unidade de temporizador, escrever agendamentos por calendário e por intervalo, habilitar o temporizador e verificar a próxima execução e os logs.
- Agendar tarefas com cron
Guia de estudo de Scripts de shell
1Escrever e executar seus primeiros scripts Bash
Alguns comandos ficam mais fáceis de repetir quando estão em um único script. Você indicará um interpretador Bash para o arquivo, manterá suas instruções legíveis e escolherá como iniciá-lo. As permissões de arquivo, os caminhos de busca de comandos e os shells filhos explicam algumas situações comuns: por que um script funciona com bash, mas falha com ./, por que seu nome não é encontrado e por que suas mudanças de diretório não movem seu terminal.
1.1 Transformar comandos repetidos em um arquivo de script
Um script de shell salva uma sequência de comandos em um arquivo de texto simples. O Bash lê os comandos em ordem, assim como lê os comandos que você digita em um prompt. Um script pode repetir uma tarefa sem que alguém digite cada etapa e oferece um único lugar para corrigir ou melhorar essa tarefa.
Coloque o interpretador na primeira linha
O shebang informa ao Linux qual programa deve ler um script executável. Comece um script Bash com #!/bin/bash. #! deve ser os dois primeiros caracteres do arquivo: sem espaços ou linha em branco antes deles. Bash significa Bourne Again Shell. Ele é amplamente usado como shell interativo no Linux e também lê arquivos de script.
Um interpretador é um programa que lê e executa outra linguagem. O mesmo mecanismo permite que #!/usr/bin/python3 selecione o Python ou que #!/usr/bin/awk -f selecione o awk. O restante de um script Bash deve conter comandos de shell que o Bash entenda.
Crie backup-notes.sh em um editor de texto simples, como nano ou vi:
#!/bin/bash
# Keep a copy of the notes and show the backup folder.
mkdir -p ~/backup
cp ~/notes.txt ~/backup/
ls -l ~/backup
O Bash primeiro cria o diretório de destino, depois copia as anotações e, em seguida, lista o destino. mkdir -p também é bem-sucedido quando o diretório já existe, portanto uma execução posterior pode reutilizá-lo. O arquivo de origem ~/notes.txt deve existir para que a cópia funcione. Salvar os comandos não cria esse arquivo de origem.
Torne o arquivo legível para as pessoas
A segunda linha é um comentário. Fora de texto entre aspas, # inicia um comentário no começo de uma palavra; o Bash ignora o restante dessa linha. Escreva comentários sobre a finalidade de uma etapa, como o motivo para manter uma cópia de segurança. Linhas em branco e indentação facilitam a identificação de grupos de comandos. Mantenha a indentação consistente ao adicionar condições e laços.
A terminação .sh ajuda o leitor a reconhecer um script de shell. O Linux não exige essa terminação, e adicioná-la não seleciona o Bash nem concede permissão de execução. Um arquivo chamado backup-notes pode executar os mesmos comandos.
Escolha o shell adequado à linguagem
| Primeira linha | Como o interpretador é escolhido |
|---|---|
#!/bin/bash | Usa o Bash no caminho fixo /bin/bash. |
#!/usr/bin/env bash | Usa env para encontrar o Bash por meio do PATH. |
#!/bin/sh | Usa o sh do sistema, que pode ser outro shell. |
No Debian e no Ubuntu, /bin/sh normalmente seleciona o dash. Recursos do Bash, como [[ ... ]], falham nele. Um script Bash precisa de um interpretador Bash, mesmo que comandos simples funcionem em ambos os shells. Chamar um arquivo de something.sh não corrige um shebang incompatível.
Reconheça um problema de terminador de linha
Editores do Windows podem salvar um retorno de carro antes de cada caractere de nova linha. No Linux, esse caractere invisível pode se tornar parte do caminho no shebang. Um erro como /bin/bash^M: bad interpreter: No such file or directory aponta para esse problema, mesmo que /bin/bash exista.
Converta o arquivo para terminadores de linha do Unix com dos2unix backup-notes.sh e, depois, salve os próximos scripts com terminadores de linha do Unix no editor. Os comandos do arquivo podem estar corretos enquanto o caractere extra impede o Linux de iniciar seu interpretador.
Principais conclusões
- Um script é um texto simples que contém comandos a serem executados em ordem.
- O shebang deve começar no início do arquivo e indicar o interpretador correto.
- Use comentários e indentação para deixar claras a finalidade e a estrutura.
- A extensão
.shé uma convenção; ela não seleciona um shell. - Terminadores de linha do Unix impedem que um retorno de carro oculto prejudique o shebang.
1.2 Executar um script e escolher onde armazená-lo
Um script pode ser lido diretamente pelo Bash ou iniciado como um programa. Essas formas diferem nas permissões necessárias e em como o interpretador é escolhido. O caminho digitado também determina se o shell busca um comando ou usa um arquivo específico.
Duas maneiras de iniciar o mesmo arquivo
bash backup-notes.sh
chmod u+x backup-notes.sh
./backup-notes.sh
O primeiro comando inicia o Bash e pede que ele leia o arquivo. O script precisa de permissão de leitura; seu próprio bit de execução não é necessário. O Bash trata o shebang como comentário porque o interpretador já foi escolhido.
O segundo comando adiciona permissão de execução para o proprietário do arquivo. Em uma sequência de permissões como -rwxr--r--, o x do proprietário significa que o arquivo é executável. O terceiro comando executa o arquivo como um programa e usa seu shebang. chmod +x também é comum; sem uma classe de permissões indicada, a umask limita quais classes recebem permissão de execução. chmod u+x direciona a alteração explicitamente ao proprietário.
Se ./backup-notes.sh informar “Permission denied”, verifique a permissão de execução e o acesso ao caminho. Se bash backup-notes.sh funcionar, isso não comprova que a execução direta tenha as permissões necessárias.
Entenda a busca de comandos
./ significa o diretório atual. Quando um comando contém uma barra, o Bash segue esse caminho. Quando você digita um nome sem barra, o Bash busca nos diretórios do PATH. O diretório atual normalmente está ausente dessa lista, portanto estar dentro do diretório de um script não basta para executá-lo apenas pelo nome.
echo "$PATH"
command -v backup-notes.sh
type backup-notes.sh
PATH é uma lista separada por dois-pontos, como /home/sam/.local/bin:/usr/local/bin:/usr/bin:/bin. O primeiro executável correspondente prevalece. Os dois últimos comandos ajudam a identificar o que será executado para um nome, incluindo uma cópia mais antiga em outro lugar do PATH.
Para disponibilizar um script pessoal pelo nome, coloque-o em um diretório do seu PATH. Muitas distribuições adicionam ~/bin ou ~/.local/bin no login quando esse diretório existe; confira seu PATH. /usr/local/bin é um local comum para scripts compartilhados entre usuários e exige direitos de administrador para gravação.
Escolha um shell filho ou o shell atual
Executar ./settings.sh ou bash settings.sh inicia um processo Bash filho. Suas variáveis e mudanças de diretório pertencem a esse processo filho. Um script que contém cd /var/log não muda o diretório do terminal que o iniciou. Quando ele termina, você ainda está no diretório original do terminal.
A execução no shell atual (sourcing) lê comandos no shell atual:
source ./settings.sh
# Equivalent short form:
. ./settings.sh
Use essa forma para um arquivo de configuração destinado a alterar sua sessão. Ela exige permissão de leitura, não de execução, e um shebang não inicia um interpretador separado. Portanto, executar um arquivo de configuração Bash no shell atual pressupõe que esse shell entenda a sintaxe do Bash.
Leia o resultado de uma execução
Imediatamente após o término de um script, echo $? mostra seu código de saída. A menos que o script use exit com um código escolhido, seu código vem do último comando. Assim, uma listagem final bem-sucedida pode ocultar uma falha anterior na cópia; as verificações de erro apresentadas mais adiante permitirão que o script informe o resultado real da tarefa.
Principais conclusões
bash filelê um script com o Bash;./fileexige permissão de execução e usa o shebang.- O PATH é consultado apenas para nomes de comando sem barra.
- Verifique um nome de comando com
command -voutype. - A execução inicia um shell filho; a execução no shell atual pode alterá-lo.
2Armazenar valores em variáveis e protegê-los com aspas com segurança
Variáveis permitem que os mesmos comandos funcionem com caminhos, nomes e contagens que mudam. As aspas mantêm esses valores intactos enquanto o Bash monta uma linha de comando, de modo que um espaço em um nome continue fazendo parte dele. Você lerá entradas, passará valores a programas filhos, capturará a saída de comandos e calculará com números inteiros. Esses recursos funcionam juntos quando um script cria um nome de arquivo com data ou mantém uma contagem acumulada.
2.1 Criar, ler e exportar variáveis
Uma variável dá um nome a um valor para que o mesmo script possa reutilizá-lo. Variáveis do Bash normalmente armazenam texto, mesmo quando esse texto parece um número. Você atribui o valor uma vez e expande o nome sempre que um comando precisar dele.
Faça atribuições sem espaços
city=Lisbon
greeting="Good morning"
echo "$greeting from $city"
A saída é “Good morning from Lisbon.” Não há espaços ao redor do = de atribuição. Em city = Lisbon, o Bash trata city como comando e as outras palavras como argumentos. As aspas ao redor de "Good morning" mantêm as duas palavras em um único valor.
Use letras, dígitos e sublinhados nos nomes de variáveis, começando com uma letra ou um sublinhado. Os nomes diferenciam maiúsculas de minúsculas: file, File e FILE são diferentes. Escolha nomes em minúsculas, como backup_dir, para valores pertencentes ao seu script. Isso ajuda a evitar a substituição de variáveis de ambiente como PATH ou HOME. Definir PATH=/data altera a localização de comandos e pode fazer com que comandos comuns deixem de ser encontrados.
Marque onde um nome termina
Um cifrão introduz uma expansão. As chaves mostram o limite quando há mais texto imediatamente em seguida:
file=report
echo "${file}_old"
Isso imprime “report_old.” Com "$file_old", o Bash procura uma variável chamada file_old, não file seguida de _old. Sem set -u, um nome não definido é expandido para texto vazio. Assim, um erro de digitação pode produzir um caminho ou uma mensagem vazia sem erro imediato.
Um valor como count=5 armazena o texto “5.” Adicionar texto ao lado de uma expansão não faz um cálculo: echo "$count+1" imprime “5+1.” A expansão aritmética dá aos números um papel diferente quando cálculos são necessários.
Leia uma linha de entrada
read -r -p "Your name: " name
echo "Hello, $name"
read armazena a linha digitada em name. -p fornece o prompt e -r preserva as barras invertidas. Com a entrada “Lee Kim”, a saudação é “Hello, Lee Kim.” Um script executado sem uma pessoa presente precisa receber suas entradas de argumentos, arquivos ou valores padrão; um prompt não pode fornecer um valor ausente de maneira confiável.
Exporte valores para programas filhos
Uma variável comum do shell pertence ao shell no qual é definida. A exportação marca a variável para inclusão no ambiente copiado aos programas que esse shell inicia:
export BACKUP_DIR=/mnt/usb
bash backup-notes.sh
O Bash filho agora pode ler BACKUP_DIR. Se esse processo filho atribuir outro valor, o processo pai mantém seu próprio valor. A herança do ambiente passa do processo pai para o filho; ela não envia alterações posteriores de volta.
| Nome | Significado usual |
|---|---|
HOME | Diretório pessoal |
USER | Nome de usuário |
PWD | Diretório de trabalho atual |
PATH | Diretórios pesquisados para nomes de comandos |
env ou printenv exibe variáveis de ambiente. unset name remove a variável chamada name; ele não atribui uma string vazia. Na expansão normal, ambos podem parecer vazios, mas uma verificação de variável não definida pode distinguir uma variável ausente de uma definida.
Principais conclusões
- Atribuições usam
name=valuesem espaços ao redor de=. - Nomes de variáveis diferenciam maiúsculas de minúsculas; use nomes em minúsculas para seus próprios valores.
${name}marca o fim de um nome de variável antes de texto adjacente.read -rlê a entrada preservando as barras invertidas.- Valores exportados são copiados para processos filhos, nunca de volta para um processo pai.
unsetremove uma variável.
2.2 Proteger palavras, variáveis e caracteres especiais com aspas ou escape
O Bash lê um comando antes de o programa receber seus argumentos. Espaços separam palavras, e caracteres como *, ?, $, ;, &, |, < e > têm funções especiais. A proteção com aspas ou escape controla quais dessas funções permanecem ativas.
Escolha o que deve ser expandido
| Forma | O que o Bash faz |
|---|---|
'fixed text' | Mantém tudo dentro das aspas como literal. |
"text with $name" | Preserva espaços e caracteres curinga, mas expande variáveis, saída de comandos e expressões aritméticas. |
\* | Trata o próximo caractere literalmente fora de aspas. |
Com HOME=/home/sam, compare:
echo 'Home: $HOME *'
echo "Home: \$HOME *"
O primeiro imprime “Home: $HOME *”. O segundo imprime “Home: /home/sam *”. O asterisco permanece literal em ambos, mas apenas as aspas duplas permitem que a variável seja expandida. Uma aspa simples não pode ser colocada diretamente dentro de uma string entre aspas simples.
Dentro de aspas duplas, barras invertidas podem proteger um cifrão, uma crase, uma aspa dupla ou uma barra invertida. Por exemplo, echo "Price: \$5" imprime “Price: $5”. Fora de aspas, echo 5 \* 3 imprime “5 * 3”, e touch my\ file.txt cria um arquivo com um espaço no nome.
Acompanhe um valor sem aspas pelo Bash
file="my report.txt"
cp $file backup/
Primeiro, o Bash expande a variável. Depois, a separação de palavras divide seu valor em espaços, tabulações e caracteres de nova linha. O comando recebe my, report.txt e backup/ como argumentos separados. Ele tenta copiar dois arquivos de origem em vez do único arquivo pretendido.
Se uma palavra resultante contiver caracteres curinga, a expansão de nomes de arquivo a substitui pelos nomes correspondentes. Um valor armazenado de *.txt pode se tornar vários argumentos de arquivo quando expandido sem aspas. Essas etapas adicionais ocorrem antes de cp iniciar; o programa não consegue recuperar o agrupamento pretendido.
cp "$file" backup/
Agora o valor expandido permanece como um argumento, “my report.txt”. Os próprios caracteres de aspas são removidos pelo Bash; eles são instruções de interpretação, não parte do caminho passado a cp. Coloque aspas duplas ao redor de expansões de variáveis e substituições de comando sempre que seu valor completo deva permanecer junto.
Mantenha presente um valor vazio
As aspas também importam quando um valor está vazio. Em [ $answer = yes ], um answer vazio desaparece, deixando um teste inválido. [ "$answer" = yes ] passa uma string vazia como um argumento, portanto o teste é válido e falso.
A mesma regra de agrupamento se aplica a palavras literais. mkdir new folder cria dois diretórios, enquanto mkdir "new folder" cria um. Colocar um caminho inteiro entre aspas é útil tanto quando seu espaço foi digitado diretamente quanto quando veio de uma variável.
Combine texto literal e expandido
Partes adjacentes entre aspas, sem espaço entre elas, formam uma palavra. Com price=8, echo 'Price: $'"$price" imprime “Price: $8”. A parte fixa está entre aspas simples e a parte variável está entre aspas duplas. Um padrão de busca também pode ser mantido fixo: grep 'cost: \$[0-9]' prices.txt passa seu padrão sem expansão pelo shell, deixando que grep o interprete.
Principais conclusões
- Aspas simples mantêm o texto literal; aspas duplas permitem expansões e mantêm os valores juntos.
- Expansões sem aspas passam pela separação de palavras e depois pela expansão de nomes de arquivo.
- Aspas preservam um valor vazio como argumento.
- Uma barra invertida pode tornar literal um caractere especial.
- Partes adjacentes entre aspas formam uma palavra quando não há espaço entre elas.
2.3 Capturar a saída de comandos e calcular com números inteiros
Comandos muitas vezes produzem um valor necessário em outra etapa. O Bash pode capturar essa saída, colocá-la dentro de um texto ou usá-la em um cálculo. A substituição de comando e a expansão aritmética têm pontuação semelhante, mas cumprem funções diferentes.
Capture a saída padrão
today=$(date +%F)
cp notes.txt "notes-${today}.txt"
$(...) executa um comando e substitui a expressão por sua saída padrão. Em 2026-10-22, today contém “2026-10-22” e a cópia recebe o nome notes-2026-10-22.txt. Uma data na ordem ano-mês-dia mantém os nomes de arquivo em ordem de data quando são ordenados pelo nome. Você também pode colocar a substituição diretamente no nome: "notes-$(date +%F).txt".
Os caracteres de nova linha no final são removidos da saída capturada. A forma mais antiga com crases também captura a saída, mas $(...) é mais fácil de ler e aninhar. Coloque entre aspas uma substituição usada como argumento de comando, como "$(date +%F)", para manter seu resultado junto.
A substituição de comando captura apenas a saída padrão. Erros enviados à saída de erro padrão ainda vão para seu destino habitual. result=$(some_command 2>&1) combina ambos os fluxos dentro da captura quando isso é o que o script precisa. Misturar erros a um valor destinado a conter um número faria a aritmética posterior falhar.
Capture uma contagem sem o nome do arquivo
lines=$(wc -l < access.log)
echo "Lines: $lines"
Se o arquivo contiver 342 caracteres de nova linha, wc fornece a contagem 342. Redirecionar o arquivo para wc faz sua saída conter apenas a contagem; wc -l access.log também imprime o nome do arquivo. Um resultado com aparência numérica pode então ser reutilizado, desde que o comando tenha sido bem-sucedido.
Calcule com números inteiros
$(( ... )) realiza a expansão aritmética:
echo "$(( 17 / 5 ))"
echo "$(( 17 % 5 ))"
Os resultados são 3 e 2. A divisão inteira descarta o resto; % o retorna. Adição, subtração e multiplicação usam +, - e *. Nomes de variáveis podem aparecer sem cifrão dentro da expressão: total=$(( price * qty )).
Com a=5, echo "$a+3" imprime “5+3” como texto. echo "$(( a + 3 ))" calcula e imprime 8. Os parênteses adicionais selecionam a aritmética; $(a + 3) tentaria executar um comando chamado a.
Um contador começa com um valor como count=0 e é atualizado com count=$(( count + 1 )). O Bash também oferece (( count++ )); esse é um comando aritmético com seu próprio código de saída, o que importa em scripts que usam opções de erro.
Mantenha a precisão necessária
A aritmética do Bash usa números inteiros. 7 / 2 resulta em 3, e um valor decimal como 2.5 causa um erro de sintaxe aritmética. Uma ferramenta separada pode calcular com decimais:
echo "scale=2; 7 / 2" | bc
Isso produz 3.50. Na aritmética inteira, multiplique antes de dividir quando o produto preservar uma fração de que você ainda precisa. Para 45 de 60, $(( 45 * 100 / 60 )) resulta em 75. Dividir primeiro resulta em zero para 45 / 60, portanto $(( 45 / 60 * 100 )) permanece zero; a fração perdida não pode ser recuperada pela multiplicação posterior.
Principais conclusões
$(command)captura a saída padrão e remove os caracteres de nova linha no final.$((expression))calcula com números inteiros.- Use
/para divisão inteira e%para seu resto. - Um contador armazena seu valor atualizado após cada incremento.
- Multiplicar antes de dividir pode evitar a perda prematura de precisão na aritmética inteira.
- Use uma ferramenta como
bcquando for necessário um resultado decimal.
3Informar sucesso e falha com códigos de saída
Um script precisa de um resultado que tanto pessoas quanto programas possam entender. A saída impressa explica o que aconteceu, enquanto um código de saída permite que outro comando decida se deve continuar. Você salvará esse código, verificará etapas dependentes e manterá visíveis as falhas em encadeamentos. Verificações de sintaxe, rastreamentos de execução e opções de erro ajudam a encontrar a causa de uma falha antes que comandos posteriores tornem seus efeitos mais difíceis de identificar.
3.1 Ler e definir códigos de saída e usá-los para encadear comandos
Um comando informa seu resultado de duas maneiras: ele pode imprimir texto e retorna um código de saída. Programas usam esse código para decidir o que acontece em seguida. Um script pode imprimir uma mensagem tranquilizadora e ainda assim ter falhado, ou não imprimir nada e ser bem-sucedido.
Leia um código antes que ele mude
Um código de saída é um número inteiro de 0 a 255. Zero significa sucesso. Um valor diferente de zero informa uma falha ou outro resultado documentado. grep, por exemplo, usa 0 para uma correspondência, 1 para nenhuma correspondência e 2 para um erro. Uma busca sem correspondência pode ser um resultado normal para sua tarefa, embora seu código seja diferente de zero.
$? armazena o código do comando mais recente:
grep -q root /etc/passwd
status=$?
echo "Search status: $status"
A atribuição salva o resultado antes que outro comando o substitua. Em ls /missing; echo $?; echo $?, o ls do GNU retorna 2 para o caminho inacessível fornecido na linha de comando. O primeiro echo imprime 2 e depois é bem-sucedido. O segundo imprime 0, o código desse echo, não da listagem original.
Termine com um resultado útil
exit 1 encerra um script imediatamente e informa 1 a quem o chamou. exit 0 informa sucesso. Um exit sem número usa o código do comando anterior; chegar ao fim normalmente usa o código do último comando. Escolha códigos entre 0 e 255: exit 256 dá a volta para 0 e informaria sucesso incorretamente.
Alguns códigos vêm do próprio Bash:
| Código | Significado |
|---|---|
| 127 | O comando não foi encontrado. |
| 126 | O comando foi encontrado, mas não pôde ser executado. |
128 + n | O comando terminou por causa do sinal de número n. |
Ctrl+C envia o sinal 2, portanto um comando encerrado dessa forma costuma informar 130. Programas comuns também documentam seus próprios códigos; 1 e 2 não têm um significado universal para todas as ferramentas.
Encadeie comandos dependentes
mkdir -p ~/backup && cp notes.txt ~/backup/
cd /data/reports || exit 1
&& executa o próximo comando apenas após um sucesso. Aqui, a cópia depende da criação ou localização do diretório de cópia de segurança. || executa o próximo comando apenas após uma falha. Aqui, uma mudança de diretório malsucedida interrompe o script antes que comandos posteriores usem o diretório de trabalho errado.
true retorna 0; false retorna 1. Um ! no início inverte o sucesso ou a falha de um comando. ! grep -q ERROR app.log é bem-sucedido quando a busca não encontra uma linha correspondente, embora também seja bem-sucedido se grep falhar com um erro; use verificações explícitas do código de saída quando for necessário distinguir esses resultados.
Verifique um encadeamento inteiro
grep ERROR missing.log | wc -l
Por padrão, um encadeamento tem o código de saída de seu comando final. grep falha devido ao arquivo ausente, mas wc lê um fluxo vazio, imprime 0 e é bem-sucedido. Portanto, o código do encadeamento é 0.
set -o pipefail faz um encadeamento falhar quando qualquer um de seus comandos falha. Ele informa o código diferente de zero mais à direita, ou 0 se todos os comandos forem bem-sucedidos. Isso torna os erros anteriores no encadeamento visíveis para if, &&, || e quem chamou o script. Um agendador pode então distinguir um relatório bem-sucedido de um que nunca leu sua entrada.
Principais conclusões
- O código de saída 0 significa sucesso; resultados diferentes de zero têm significados documentados por cada programa.
- Salve
$?imediatamente se precisar usá-lo após outro comando. exitfornece um resultado a quem chamou o script.&&continua após o sucesso, e||continua após a falha.- Sem
pipefail, um encadeamento informa apenas o código de saída de seu último comando.
3.2 Encontrar erros e encerrar um script com segurança
O Bash normalmente continua após a falha de um comando. Se o próximo comando depender desse trabalho, continuar pode transformar uma pequena falha em um problema maior. Verifique explicitamente as etapas dependentes e use a verificação de sintaxe e o rastreamento para descobrir por que uma execução se comporta de forma diferente do planejado.
Interrompa a execução antes que uma falha se propague
cd /backups || exit 1
Agora, os comandos seguintes só podem ser executados após uma mudança de diretório bem-sucedida. Isso importa antes de operações com arquivos: se uma mudança de diretório falhar e o script continuar, os caminhos relativos ainda se referirão ao diretório antigo. Verifique o destino antes de executar comandos que alteram ou excluem arquivos.
Uma mensagem de erro e um código de falha atendem a leitores diferentes:
echo "Error: $file not found" >&2
exit 1
A mensagem vai para a saída de erro padrão, deixando a saída padrão disponível para dados. Com ./report.sh > report.txt, a mensagem permanece visível no terminal enquanto a saída normal entra no arquivo. O código diferente de zero permite que outro programa detecte o erro sem ler a frase.
Verifique a sintaxe e depois rastreie a execução
| Comando | O que faz |
|---|---|
bash -n script.sh | Lê a sintaxe sem executar comandos. |
bash -x script.sh | Executa o script e imprime os comandos expandidos antes de executá-los. |
A falta de fi, done ou de uma aspa de fechamento é um problema de sintaxe. bash -n pode localizá-lo, muitas vezes por meio de uma mensagem “unexpected end of file”. Um caminho de arquivo com sintaxe válida, mas digitado incorretamente, precisa de uma verificação durante a execução.
O rastreamento precede os comandos com +. Uma linha como cp "$src" "$dest" revela os caminhos reais recebidos. set -x e set +x ativam e desativam o rastreamento em torno de uma seção.
Entenda as opções de erro
set -euo pipefail combina três controles:
-eencerra a execução após uma falha de comando não tratada.-uinforma uma variável não definida como erro.pipefailfaz com que falhas de comandos afetem o código de saída do encadeamento.
-e permite falhas esperadas em condições if, while e until, comandos negados e comandos que não são os últimos em listas && ou ||. Sem pipefail, uma falha antes do comando final de um encadeamento não provoca a saída. Verificações explícitas continuam úteis porque indicam o que o script deve fazer quando uma etapa específica falha.
Um comando aritmético também informa verdadeiro ou falso. (( count++ )) retorna o código 1 quando o valor antigo é 0, portanto um uso não tratado sob -e pode interromper o script mesmo que o incremento tenha ocorrido. A atribuição count=$(( count + 1 )) evita esse código de saída do comando aritmético.
-u detecta um erro de digitação como $filname quando apenas filename foi definida. Ele não rejeita uma variável que existe, mas está vazia. ${dir:?not set} verifica se dir está ausente ou vazia nessa expansão. Um resultado esperado sem correspondência pode ser tratado com um teste; command || true suprime todas as falhas desse comando, portanto use-o apenas quando todas elas forem aceitáveis.
Leia as mensagens e faça a limpeza
“Command not found” aponta para um problema no nome, no programa instalado ou no PATH. “Permission denied” aponta para execução ou acesso a arquivo. “Unary operator expected” normalmente decorre de um valor vazio sem aspas em [ ]; “integer expression expected” significa que um teste numérico recebeu texto.
Um trap em EXIT define uma ação de limpeza, como trap 'rm -f "$tmpfile"' EXIT, depois que tmpfile recebe um valor. O comando entre aspas é executado quando o Bash sai, inclusive após um exit explícito ou uma saída por erro sob -e. O ShellCheck também pode inspecionar scripts antes da execução em busca de erros comuns de proteção com aspas e de lógica.
Principais conclusões
- Verifique uma etapa antes de executar comandos que dependem dela.
- Escreva mensagens de diagnóstico na saída de erro padrão e informe falhas com um código diferente de zero.
bash -nverifica a sintaxe;bash -xexecuta e rastreia.set -etem exceções para falhas que estão sendo testadas.set -udetecta variáveis não definidas, enquanto${name:?message}também rejeita valores vazios.- Um trap em EXIT pode remover um arquivo temporário quando o script termina.
4Tomar decisões e repetir tarefas
Um script útil escolhe ações e as repete para entradas que mudam. Testes transformam perguntas sobre arquivos, textos e números em sucesso ou falha. Ramos selecionam uma ação, enquanto laços aplicam comandos a listas ou continuam até que uma condição mude. Você acompanhará o valor usado em cada passagem e preservará espaços, registros e contadores enquanto os dados percorrem o script.
4.1 Testar arquivos, strings e números
Uma condição no Bash é um comando cujo código de saída significa verdadeiro ou falso. Testes permitem fazer perguntas sobre caminhos, textos e números. Escolha um operador adequado ao tipo de valor; os mesmos caracteres impressos podem ter significados diferentes como texto e como número.
Separe os elementos do teste
test -f notes.txt e [ -f notes.txt ] verificam se um caminho se refere a um arquivo comum existente. [ é um comando, e seu último argumento deve ser ]. Espaços separam seus argumentos:
[ -f "$file" ]
Sem o espaço após [, o Bash pode procurar um comando chamado [-f. Em [ "$a"="$b" ], a falta de espaços ao redor de = forma uma palavra não vazia, cujo teste é verdadeiro mesmo que os valores sejam diferentes. Operadores devem ser argumentos separados.
Escolha um teste de arquivo
| Operador | Verdadeiro quando o caminho… |
|---|---|
-e | Existe. |
-f | É um arquivo comum existente. |
-d | É um diretório existente. |
-r, -w, -x | Pode ser lido, gravado ou executado pelo usuário atual. |
-s | Existe e tem tamanho maior que zero. |
-L | É um link simbólico. |
Para um diretório chamado logs, -e e -d são bem-sucedidos, enquanto -f falha. Testes de arquivo normalmente seguem um link simbólico até seu destino; -L verifica o próprio link. Portanto, um link quebrado pode satisfazer -L e falhar em -e.
Compare textos ou números inteiros
Testes de strings usam = e != para igualdade e desigualdade. -z verifica se o comprimento é zero e -n se o comprimento é diferente de zero. [ "$answer" = yes ] corresponde exatamente a “yes”; “Yes” e “yes ” são textos diferentes. Aspas duplas mantêm um valor vazio no teste.
Comparações de números inteiros usam -eq, -ne, -lt, -le, -gt e -ge: igual, diferente, menor que, menor ou igual, maior que e maior ou igual. [ "$count" -gt 100 ] verifica se o número é maior que 100.
[ 07 -eq 7 ]
[ 07 = 7 ]
A comparação numérica é bem-sucedida porque os valores são iguais. A comparação de strings falha porque um dos textos começa com um zero a mais.
Não use > isolado para um teste numérico dentro de [ ]. Em [ 10 > 9 ], o Bash redireciona a saída para um arquivo chamado 9 e testa a palavra não vazia restante. Em [[ 10 < 9 ]] no Bash, o operador compara strings, portanto o caractere inicial 1 vem antes de 9. Use -lt ou -gt para comparações numéricas, ou aritmética do Bash, como (( count > 100 )).
Combine condições
[ ! -d "$dir" ] é bem-sucedido quando o caminho não é um diretório existente; ele pode ser um arquivo comum ou estar ausente. [ -f "$f" ] && [ -r "$f" ] é bem-sucedido apenas quando ambos os testes são bem-sucedidos. Testes separados unidos por || são bem-sucedidos quando pelo menos um é bem-sucedido.
O Bash também tem a palavra-chave condicional [[ ... ]]. Ela impede a separação em palavras das expansões de variáveis e permite && e || em seu interior. Um padrão sem aspas à direita de == faz uma correspondência de padrões: [[ $file == *.log ]] corresponde a “app.log”. Colocar esse padrão entre aspas o tornaria literal. Essa sintaxe exige o Bash; dash não a implementa.
Principais conclusões
- Um teste informa verdadeiro com o código 0 e falso com o código 1.
- Coloque espaços ao redor de
[e de seus operadores e feche com]. - Testes de arquivo distinguem existência, tipo e acesso.
- A igualdade de strings compara texto; operadores numéricos comparam valores inteiros.
- Use
-gte-ltpara números, não símbolos de redirecionamento isolados. - A negação inverte um teste;
&&exige ambas as condições. [[ ... ]]do Bash aceita padrões e evita a separação de palavras.
4.2 Escolher ações com if, elif, else e case
Condições se tornam úteis quando selecionam ações. Um bloco if escolhe um ramo com base nos resultados de comandos. Um bloco case seleciona um ramo comparando um valor com padrões. Ambos tornam visíveis as ações disponíveis no script.
Deixe um comando escolher um ramo
if grep -q ERROR app.log; then
echo "Errors found"
else
echo "No successful match"
fi
if executa o comando e entra no primeiro ramo quando ele retorna 0. Caso contrário, entra em else. A própria busca é a condição; não é necessário executá-la, imprimir algo e depois examinar $?. Um erro de grep também retorna um valor diferente de zero, portanto este exemplo descreve o ramo else como ausência de correspondência bem-sucedida, não como prova de que o arquivo não contém erros.
then deve iniciar um novo comando: coloque-o na linha seguinte ou após um ponto e vírgula. fi fecha o bloco. A falta de fi muitas vezes produz um erro de sintaxe de fim de arquivo porque o Bash ainda está esperando o fechamento do bloco.
Ordene condições sobrepostas
elif adiciona um teste executado apenas quando os testes anteriores falharam. Para uma porcentagem inteira de uso de disco:
if [ "$usage" -ge 90 ]; then
echo "CRITICAL: disk ${usage}% full"
elif [ "$usage" -ge 75 ]; then
echo "WARNING: disk ${usage}% full"
else
echo "OK: disk ${usage}% full"
fi
Com usage=82, o primeiro teste falha e o segundo é bem-sucedido, produzindo “WARNING: disk 82% full”. Com 95, o primeiro ramo é executado e o ramo de aviso é ignorado. Se o teste de 75 viesse primeiro, 95 corresponderia a ele e nunca chegaria ao teste crítico. Organize intervalos sobrepostos para que a condição mais restritiva seja verificada primeiro.
Apenas o primeiro ramo bem-sucedido é executado. else não precisa de condição e trata o que resta. Tanto elif quanto else podem ser omitidos quando a tarefa não precisa deles.
Compare um valor com case
case "$1" in
start) echo "Starting" ;;
stop) echo "Stopping" ;;
y|Y|yes) echo "Confirmed" ;;
*) echo "Usage: $0 start|stop|y|Y|yes" >&2; exit 2 ;;
esac
Cada padrão termina com ), cada ramo termina com ;; e esac fecha o bloco. O | dentro de um padrão fornece alternativas. O * final corresponde a qualquer valor e fica por último porque abrange todos eles.
case usa padrões de nomes de arquivo, não expressões regulares. *.jpg corresponde a um valor terminado em .jpg. [0-9]* corresponde a um valor cujo primeiro caractere é um dígito; o * pode corresponder a qualquer texto seguinte, portanto também corresponde a “7draft”. Isso não prova que um valor inteiro contenha apenas dígitos.
Escolha a estrutura adequada
Use case quando uma entrada, como um subcomando ou uma resposta, tiver várias formas identificadas. Use if quando as condições examinarem coisas diferentes, como a existência de um arquivo e se uma contagem ultrapassa um limite. Uma correspondência de padrão verifica os caracteres de um valor; um teste de arquivo verifica o caminho no disco. Um nome terminado em .log pode corresponder a um padrão mesmo quando esse arquivo não existe.
Principais conclusões
ifescolhe um ramo pelo código de saída de um comando; qualquer comando pode ser uma condição.- Testes
elifsó são executados após a falha das condições anteriores. - Ordene limites sobrepostos do mais restritivo ao mais abrangente.
caseseleciona o primeiro padrão correspondente e usa;;para encerrar cada ramo.- Uma correspondência de padrão não comprova que um arquivo existe.
4.3 Repetir comandos para itens de listas e arquivos com for
Um laço for fornece ao mesmo corpo de comandos um novo valor a cada passagem. A lista pode conter palavras literais, nomes de arquivo correspondentes, um intervalo de números ou os argumentos do script. O Bash atribui um item da lista à variável do laço antes de executar o corpo.
Percorra uma lista fixa
for host in web1 web2 db1; do
echo "Checking $host"
done
A primeira passagem tem host=web1, a segunda host=web2 e a terceira host=db1. O laço imprime três linhas. do abre o corpo e done o fecha. A variável permanece disponível após o laço, contendo seu último valor atribuído.
Um laço também pode acumular um resultado:
total=0
for n in 4 8 15; do
total=$(( total + n ))
done
echo "$total"
O total armazenado muda de 0 para 4, depois 12 e depois 27. Inicialize o total antes do laço para que a primeira soma tenha um valor inicial definido.
Percorra arquivos correspondentes
for f in *.log; do
[ -f "$f" ] || continue
gzip -- "$f"
done
O Bash expande o padrão para os nomes correspondentes antes de executar o corpo do laço. Cada nome de arquivo correspondente permanece como um item da lista, mesmo que contenha espaços. Colocar "$f" entre aspas dentro do corpo mantém esse item junto quando ele é passado a gzip. Aqui, o teste de arquivo comum também ignora diretórios com nomes terminados em .log.
Com as configurações padrão de expansão de nomes de arquivo do Bash, um *.log sem correspondência permanece literal. Um laço sem verificação seria executado uma vez com os caracteres *.log e o comando falharia. [ -e "$f" ] || continue ignora caminhos inexistentes; use -f quando quiser apenas arquivos comuns.
Não construa um laço de nomes de arquivo a partir de $(ls). Sua saída é texto, portanto a separação de palavras pode transformar “my report.txt” em dois itens da lista. Um padrão já produz os nomes de arquivo com seus limites intactos.
Crie um novo nome a partir de cada nome antigo
for f in *.jpeg; do
[ -f "$f" ] || continue
mv -- "$f" "${f%.jpeg}.jpg"
done
${f%.jpeg} remove a terminação .jpeg do valor. Para “beach day.jpeg”, o destino se torna “beach day.jpg”. Os dois argumentos entre aspas mantêm ambos os caminhos intactos. -- informa a mv que os argumentos seguintes são nomes, mesmo que um comece com -. Use uma pasta de destino sem nomes conflitantes ao experimentar o exemplo, pois mv pode substituir um destino existente.
Conte em um intervalo
for i in {1..5} fornece os números de 1 a 5. O Bash expande as chaves antes de expandir variáveis, portanto {1..$n} não produz um intervalo de comprimento variável. Para um limite armazenado, use a forma aritmética:
for (( i = 1; i <= n; i++ )); do
echo "$i"
done
A primeira expressão inicializa o contador, a do meio o testa antes de cada passagem e a última o atualiza. for i in $(seq 1 "$n") também produz uma lista de números para um limite inteiro positivo adequado. A substituição intencionalmente sem aspas fornece números separados.
Para argumentos, for arg in "$@" fornece um item por argumento original. A forma mais curta for arg; do significa a mesma coisa, incluindo a preservação de espaços dentro de cada argumento.
Principais conclusões
- Um laço
forexecuta seu corpo uma vez por item da lista. - Padrões de nomes de arquivo fornecem nomes completos; coloque a variável do laço entre aspas no corpo.
- Um padrão sem correspondência permanece literal nas configurações padrão do Bash, portanto faça verificações em laços de arquivos.
- Evite laços de nomes de arquivo construídos a partir de
$(ls). - Intervalos entre chaves são definidos antes da expansão de variáveis; use um laço aritmético para um limite variável.
"$@"preserva os limites dos argumentos originais.
4.4 Repetir comandos até que uma condição mude com while e until
Algumas repetições terminam quando uma condição muda, não quando uma lista acaba. while e until testam a condição antes de cada passagem. O corpo de while é executado enquanto sua condição é bem-sucedida; o corpo de until é executado enquanto sua condição falha. Qualquer um dos laços pode ser executado zero vezes.
Atualize aquilo de que a condição depende
i=1
while [ "$i" -le 3 ]; do
echo "Attempt $i"
i=$(( i + 1 ))
done
A condição primeiro vê 1, depois 2 e depois 3. O corpo imprime esses três números de tentativa e aumenta o contador a cada vez. Após a atualização para 4, o teste seguinte falha e o laço termina. Se a atualização estivesse ausente, i permaneceria em 1 e o laço continuaria executando. Ctrl+C interrompe um laço em primeiro plano que esteja em execução.
Para aguardar um arquivo:
until [ -f /tmp/export.done ]; do
sleep 5
done
Se o arquivo já existir, o corpo do laço nunca será executado. Caso contrário, sleep 5 pausa por cinco segundos antes da próxima verificação. Uma pausa impede que o laço teste continuamente e desperdice tempo do processador.
Leia registros como linhas
while IFS= read -r line; do
echo "Host: $line"
done < hosts.txt
read fornece uma linha a cada passagem e retorna um código de falha no fim do arquivo. IFS= preserva espaços no início e no fim da linha; -r mantém barras invertidas. O redirecionamento de entrada após done fornece dados a todo o laço, não apenas ao comando final.
Uma linha como “web1 production” permanece como um valor. for line in $(cat hosts.txt) separaria em espaços, tabulações e caracteres de nova linha, tratando essas duas palavras como iterações separadas. Essa forma não consegue preservar registros arbitrários baseados em linhas.
Mantenha as alterações após o laço
Um pipe para um laço, como cat hosts.txt | while read -r line; do ...; done, normalmente executa o laço em um processo filho no Bash. Um contador alterado ali é perdido para o processo pai quando o filho termina. Redirecione o arquivo para o laço quando comandos posteriores precisarem de seus valores acumulados:
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < hosts.txt
echo "$count"
Isso processa linhas terminadas por um caractere de nova linha e mantém a contagem atualizada no shell atual. Nenhum encadeamento cria um processo filho para o laço.
Trate o registro final e saídas antecipadas
Um arquivo pode terminar com texto, mas sem um caractere final de nova linha. read armazena esse último texto, mas informa falha, portanto um while read simples não entra em seu corpo para esse registro. Adicione um segundo teste para aceitar o texto não vazio armazenado:
while IFS= read -r line || [ -n "$line" ]; do
echo "Host: $line"
done < hosts.txt
break sai do laço imediatamente. continue pula os comandos restantes na passagem atual e retorna à próxima verificação da condição. Portanto, um laço while true precisa de um break, um exit ou um sinal para terminar; ele pode servir a um menu que é encerrado quando a entrada é “q”. Coloque uma atualização antes de qualquer continue que a ignoraria em um laço com contador, ou essa passagem poderá se repetir indefinidamente.
Principais conclusões
whilerepete após sucesso;untilrepete após falha.- Ambos os laços testam a condição antes de entrar em seus corpos.
- Atualize um contador ou pause um laço de verificações para que ele avance sem espera ocupada.
IFS= read -rpreserva espaços e barras invertidas em entradas baseadas em linhas.- Redirecione um arquivo para o laço para manter as variáveis alteradas no shell atual.
- Um teste adicional de string não vazia preserva um registro final sem caractere de nova linha.
breaksai de um laço;continuepula para sua próxima passagem.
5Passar argumentos para scripts
Argumentos de linha de comando permitem que um script sirva a várias tarefas sem editar seu código. Você lerá valores individuais, preservará uma lista completa de argumentos e processará opções iniciais. Antes de começar o trabalho, conte e valide as entradas, explique uma chamada correta e forneça valores padrão para entradas opcionais. O resultado pode ser executado em um prompt ou sem acompanhamento, com mensagens claras e um código de saída quando a entrada não puder ser usada.
5.1 Ler parâmetros posicionais e a quantidade de argumentos
Argumentos transformam um script com entrada fixa em um comando reutilizável. O Bash coloca as palavras após o nome do script em parâmetros posicionais. Seus limites são definidos pelo shell que faz a chamada, portanto as aspas importam tanto na chamada do script quanto no uso desses valores.
Identifique os parâmetros
./backup.sh /home/sam/docs /mnt/usb
Dentro do script, $0 é ./backup.sh, $1 é /home/sam/docs e $2 é /mnt/usb. $# é 2, a quantidade de argumentos. O script pode usar cp -r "$1" "$2" para copiar a pasta de origem para o destino sem fixar nenhum dos caminhos no código.
$0 descreve o nome usado para iniciar o script; ele não é contado em $#. Com ./greet.sh Ana "Lee Kim", o primeiro argumento é “Ana” e o segundo é “Lee Kim”. Sem as aspas ao redor do segundo nome, o script receberia três argumentos.
Use chaves após o nono argumento
$1 a $9 nomeiam os primeiros nove parâmetros posicionais. O décimo precisa de ${10}, e as posições seguintes usam a mesma forma. $10 significa a expansão de $1 seguida do caractere literal 0. Se o primeiro argumento for “Ana”, $10 se torna “Ana0” mesmo quando há um décimo argumento.
Um parâmetro omitido é expandido para texto vazio nas configurações normais. Com dois argumentos, $3 está ausente; sob set -u, expandi-lo causa um erro de variável não definida. Verifique a quantidade antes de ler posições obrigatórias ou use uma expansão que forneça um valor padrão.
Preserve todos os limites dos argumentos
Suponha que um script receba "a b" e c. Compare:
| Expansão | Palavras repassadas |
|---|---|
"$@" | Duas: “a b” e “c”. |
"$*" | Uma: “a b c”, com o separador usual de espaço. |
$@ | Três: “a”, “b” e “c” na separação normal. |
"$@" é a escolha usual para repassar argumentos:
for arg in "$@"; do
echo "Argument: $arg"
done
O laço é executado duas vezes para essa chamada, uma vez por argumento original. Sem argumentos, ele é executado zero vezes. Colocar "$@" entre aspas duplas tem um significado especial: cada parâmetro posicional permanece como uma palavra separada, portanto as aspas não unem toda a lista em uma palavra.
"$*" une valores usando o primeiro caractere de IFS, que normalmente é um espaço. Isso pode ser útil para uma única string de exibição, mas perde os limites individuais de que um comando posterior pode precisar.
Processe parâmetros com shift
shift remove o primeiro parâmetro posicional, desloca os seguintes e reduz $#. Na chamada de cópia de segurança, um shift faz $1 se tornar /mnt/usb e a contagem se tornar 1. shift 2 remove os dois primeiros parâmetros de uma vez.
Isso permite criar um laço que examina $1, o trata e depois executa shift antes da próxima passagem. Verifique se restam argumentos com [ "$#" -gt 0 ]; caso contrário, o script pode ler um valor ausente ou tentar deslocar além dos argumentos disponíveis. O deslocamento não altera $0 e não pode alterar a lista de argumentos do shell pai que iniciou o script.
Principais conclusões
$0é o nome usado na chamada, enquanto$1em diante armazenam argumentos.$#conta os argumentos, mantendo espaços entre aspas dentro de um argumento.- Use
${10}para o décimo argumento;$10é$1seguido de0. "$@"preserva os argumentos separadamente, enquanto"$*"os une.shiftremove parâmetros iniciais e altera as posições restantes.
5.2 Verificar argumentos, mostrar instruções de uso e definir valores padrão
Um script deve confirmar que sua entrada pode ser usada antes de começar o trabalho. Verifique a quantidade de argumentos e depois seu significado. Entradas opcionais podem ter valores padrão; entradas obrigatórias ausentes precisam de uma mensagem clara e de um código de saída diferente de zero.
Explique a chamada esperada
if [ "$#" -ne 2 ]; then
echo "Usage: $0 SOURCE DEST" >&2
exit 2
fi
Isso verifica a quantidade antes de expandir $1 ou $2, portanto também funciona sob set -u. A mensagem de uso vai para a saída de erro padrão. Maiúsculas nomeiam valores fornecidos pelo usuário, [DEST] significaria um destino opcional e FILE... significa um ou mais argumentos de arquivo. Uma opção de ajuda como -h normalmente imprime as instruções de uso e sai com 0 porque pedir ajuda é um uso bem-sucedido.
A quantidade de argumentos, por si só, não mostra se uma origem pode ser usada. [ -d "$1" ] verifica se há um diretório existente. Um teste de arquivo comum pode selecionar arquivos, mas a própria operação ainda precisa de uma verificação de resultado: permissões ou outros erros podem impedir uma leitura.
Use um valor padrão ou exija um valor
logdir=${1:-/var/log}
src=${1:?Usage: backup.sh SOURCE [DEST]}
A primeira forma usa /var/log quando o primeiro parâmetro está ausente ou vazio. A segunda interrompe um script não interativo em ambos os casos e imprime sua mensagem na saída de erro padrão. Os dois-pontos fazem parte de ambas as formas. Um valor padrão é usado para essa expansão; ${1:-...} não adiciona um argumento à lista de parâmetros posicionais.
Registre falhas parciais
Um script de contagem de arquivos pode continuar após uma entrada inválida e ainda informar que a tarefa inteira ficou incompleta:
#!/bin/bash
if [ "$#" -eq 0 ]; then
echo "Usage: $0 FILE..." >&2
exit 2
fi
status=0
for f in "$@"; do
if [ -f "$f" ]; then
if lines=$(wc -l < "$f"); then
echo "$f: $lines lines"
else
echo "$f: could not count lines" >&2
status=1
fi
else
echo "$f: not a regular file" >&2
status=1
fi
done
exit "$status"
Para notes.txt missing.txt, o script imprime a contagem do arquivo legível e informa o arquivo ausente, depois sai com 1. A atribuição é testada diretamente, portanto uma falha de leitura não se transforma em uma contagem vazia bem-sucedida. Um sucesso posterior nunca redefine o indicador de falha armazenado para 0.
Trate opções simples antes dos nomes de arquivo
verbose=0
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
-h) echo "Usage: $0 [-v] FILE..."; exit 0 ;;
--) shift; break ;;
-*) echo "Unknown option: $1" >&2; exit 2 ;;
*) break ;;
esac
done
Cada opção reconhecida é consumida com shift. O primeiro argumento comum encerra a análise de opções; -- também a encerra e é consumido. O "$@" restante contém os nomes de arquivo, incluindo um nome que começa com - após --. O getopts do Bash aceita uma análise mais completa de opções curtas.
Um script sem acompanhamento precisa de todas as entradas obrigatórias em argumentos, valores padrão ou configuração. read pode bloquear a execução enquanto espera um terminal ou falhar imediatamente no fim do arquivo. Substituir um argumento ausente por um prompt deixaria uma tarefa agendada sem uma forma confiável de continuar.
Principais conclusões
- Valide a quantidade antes de expandir argumentos obrigatórios.
- Uma mensagem de uso nomeia entradas obrigatórias, opcionais e repetíveis.
${1:-value}fornece um valor padrão;${1:?message}rejeita um valor ausente ou vazio.- Verifique o resultado da operação mesmo após verificar o tipo de arquivo da entrada.
- Preserve um código geral de falha ao continuar processando várias entradas.
- Consuma opções com
shifte respeite--como o fim das opções.
6Agendar a execução automática de scripts
Um script sem acompanhamento precisa de um agendamento e de uma forma de inspecionar seus resultados. O cron expressa horários correspondentes em uma linha; o systemd associa um serviço a um temporizador. Você lerá as duas formas, fornecerá o ambiente necessário à tarefa e manterá sua saída disponível. Verificar separadamente a próxima ativação e o resultado da última tarefa ajuda a distinguir um agendamento ativo de um trabalho que de fato foi bem-sucedido.
6.1 Agendar tarefas com cron
O cron inicia comandos nos horários correspondentes. O crontab de cada usuário armazena seu agendamento, e as tarefas são executadas com a identidade desse usuário. Um script agendado precisa de uma expressão de tempo correta e de um ambiente que forneça seus caminhos, entradas e destino de saída.
Leia os cinco campos
Use crontab -e para editar sua tabela e crontab -l para inspecioná-la. crontab -r exclui toda a tabela sem perguntar; use o editor para remover uma única tarefa.
| Campo, em ordem | Valores |
|---|---|
| Minuto | 0–59 |
| Hora | 0–23 |
| Dia do mês | 1–31 |
| Mês | 1–12 |
| Dia da semana | 0–7; 0 e 7 significam domingo |
30 2 * * * /home/sam/bin/backup.sh
Isso executa todos os dias às 02:30. Asteriscos aceitam todos os valores de um campo. 0 9 * * 1-5 seleciona 09:00 nos dias úteis, e 0 0 1 * * seleciona a meia-noite no primeiro dia de cada mês. Os horários usam o fuso horário do sistema, a menos que a configuração do cron especifique outro fuso compatível.
Combine intervalos, listas e passos
Uma vírgula lista valores: 1,15 no campo de dia do mês seleciona o primeiro e o décimo quinto dia. Um hífen indica um intervalo, e / introduz um passo. */15 no campo de minutos seleciona 0, 15, 30 e 45.
*/20 8-10 * * * seleciona três minutos em cada uma de três horas: nove execuções diárias, começando às 08:00 e terminando às 10:40. Os passos recomeçam dentro de seu campo. */45 executa no minuto 0 e no minuto 45 de cada hora; o intervalo até o minuto 0 da hora seguinte é de apenas 15 minutos.
Quando os campos de dia do mês e dia da semana estão ambos restritos, a correspondência de qualquer um deles basta. 0 12 13 * 5 seleciona o meio-dia no dia 13 e nas sextas-feiras, não apenas na sexta-feira 13. Os outros campos ainda precisam corresponder.
Strings especiais substituem os cinco campos: @hourly, @daily, @weekly, @monthly, @yearly e @reboot. @daily significa meia-noite, enquanto @reboot executa uma vez na inicialização.
Forneça caminhos e mantenha a saída
O cron normalmente usa /bin/sh para sua linha de comando, um PATH curto e nenhuma configuração de inicialização de shell interativo. O próprio shebang Bash de um script executável ainda seleciona o Bash. Use caminhos absolutos para o script e seus arquivos ou defina PATH no início do crontab.
30 2 * * * /home/sam/bin/backup.sh >> /home/sam/backup.log 2>&1
A tarefa acrescenta ambos os fluxos de saída ao log. Sem redirecionamento, o cron envia a saída por e-mail quando o correio está configurado, inclusive por meio de MAILTO; caso contrário, a saída pode ser perdida. Um sinal de porcentagem tem uma função especial em um comando do crontab: ele inicia uma nova linha e a entrada subsequente. Use escape em um formato de data ali, como em date +\%F. Um comando de data dentro de um script separado usa %F normalmente.
Distinga agendamentos do sistema e tarefas recuperadas
/etc/crontab e os arquivos em /etc/cron.d/ adicionam um campo de usuário após os cinco campos de tempo. Por exemplo, 30 2 * * * root /usr/local/bin/backup.sh é executado como root. Não adicione esse campo de usuário a um crontab pessoal.
Muitas distribuições também executam arquivos executáveis elegíveis em /etc/cron.daily/, /etc/cron.weekly/ e /etc/cron.monthly/. As regras padrão de nomenclatura de run-parts no Debian ignoram nomes que contêm pontos, portanto use backup-notes, não backup-notes.sh, nesses locais. O cron perde horários que passam enquanto o computador está desligado. O Anacron pode executar tarefas periódicas diárias, semanais ou mensais perdidas após a inicialização.
Principais conclusões
- Um crontab pessoal tem cinco campos de tempo seguidos diretamente por um comando.
- Listas, intervalos e passos selecionam valores dentro de cada campo.
- Quando os campos de dia do mês e dia da semana estão restritos, basta que um deles corresponda.
- Use caminhos absolutos e um log de saída para tarefas sem acompanhamento.
- Use escape em
%em um comando do crontab, inclusive em formatos de data. - Crontabs do sistema adicionam um campo de usuário; pastas periódicas também aplicam regras de elegibilidade.
- O cron perde execuções enquanto a máquina está desligada; o anacron permite recuperar tarefas periódicas.
6.2 Agendar tarefas com temporizadores do systemd
O systemd separa o trabalho de seu agendamento. Uma unidade de serviço descreve o comando a ser executado. Uma unidade de temporizador descreve quando iniciá-lo. Por padrão, backup.timer ativa backup.service, usando o nome-base compartilhado para conectar o par.
Escreva o serviço e o agendamento de calendário
Coloque estas unidades de sistema em /etc/systemd/system/:
# backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Type=oneshot é adequado para um script que é executado uma vez e termina. Use um caminho de comando absoluto e torne o script executável com um shebang Bash. O temporizador fornece o agendamento:
# backup.timer
[Unit]
Description=Run backup.service daily at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
OnCalendar corresponde a datas e horários. Aqui, a data com caracteres curinga aceita todos os dias. Persistent=true habilita a recuperação de execuções após a inatividade do temporizador: se pelo menos uma execução de calendário foi perdida, ele inicia o serviço uma vez na reativação. Ele não repete cada execução perdida.
Carregue e ative o temporizador
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Recarregue após criar ou alterar arquivos de unidade. enable --now inicia o temporizador imediatamente e o habilita para inicializações futuras. Habilitar apenas o serviço não cria um agendamento. Teste o trabalho separadamente com sudo systemctl start backup.service.
Escolha um horário ou tempo decorrido
| Configuração | Agendamento |
|---|---|
OnCalendar=Mon..Fri *-*-* 09:00:00 | Dias úteis às 09:00 |
OnCalendar=*:0/15 | Minutos 0, 15, 30 e 45 de cada hora |
OnBootSec=10min | Dez minutos após a inicialização |
OnUnitActiveSec=1h | Uma hora após a última ativação do serviço |
Expressões de calendário podem usar daily para a meia-noite de cada dia ou weekly para segunda-feira à meia-noite. Verifique uma expressão com systemd-analyze calendar "Mon..Fri 09:00" para ver sua interpretação e próxima ocorrência.
As duas últimas configurações são temporizadores monotônicos: eles medem o tempo decorrido desde um evento. Combine-os para uma primeira execução após a inicialização e ativações posteriores a cada hora. Persistent=true se aplica a temporizadores de calendário; ele não adiciona recuperação de calendário a temporizadores monotônicos.
Inspecione o agendamento e os resultados separadamente
systemctl list-timers mostra as próximas e as últimas ativações. systemctl status backup.service mostra o resultado do serviço, e journalctl -u backup.service mostra sua saída e seus erros. Uma próxima execução listada comprova que um agendamento está ativo, não que a tarefa anterior do script foi bem-sucedida.
Temporizadores têm uma janela de disparo. AccuracySec tem como padrão um minuto; AccuracySec=1s reduz a janela de agrupamento. RandomizedDelaySec adiciona deliberadamente um atraso aleatório para distribuir o trabalho entre máquinas. Essas configurações não garantem um segundo exato de início sob carga.
Execute um temporizador próprio do usuário
Arquivos de unidade de usuário ficam em ~/.config/systemd/user/, e os comandos usam systemctl --user, incluindo daemon-reload, enable --now e list-timers. Um gerenciador de usuário normalmente é executado durante a sessão desse usuário. Um administrador pode habilitar a permanência sem sessão ativa com loginctl enable-linger username para mantê-lo disponível sem login.
O cron precisa de uma linha compacta de tempo e funciona sem systemd. Temporizadores acrescentam um resultado de serviço e um diário de registros, recuperação de execuções de calendário e mais controle. Nenhum dos dois normalmente carrega ~/.bashrc; ambos precisam de scripts que funcionem com caminhos explícitos e sem prompts interativos.
Principais conclusões
- O serviço determina o que executar; o temporizador determina quando.
- Recarregue unidades alteradas e habilite o
.timercom--now. - Temporizadores de calendário seguem o relógio; temporizadores monotônicos medem o tempo desde eventos.
Persistent=truerecupera uma vez o trabalho de calendário perdido na reativação.- Verifique tanto a próxima ativação do temporizador quanto o estado e o diário de registros do serviço.
- Temporizadores de usuário precisam de um gerenciador de usuário em execução, com permanência habilitada para execuções sem sessão.
Exercícios resolvidos de Scripts de shell
1Salvar um relatório de pasta que possa ser repetido
9 passos
- 1IntroduçãoReúna uma tarefa repetida em um só lugar
Você costuma verificar onde está, listar uma pasta e imprimir uma mensagem de conclusão. Salvar os comandos permite repetir sua ordem.
Um script é um arquivo de texto simples lido por um interpretador. Você criará um pequeno relatório, selecionará o Bash explicitamente e o executará em um shell filho. O nome do arquivo, a permissão de execução e o local respondem, cada um, a uma pergunta diferente sobre como iniciá-lo.
- 2ExemploEscreva os comandos em ordem
Salve isto como
folder-report.shem um editor de texto simples:#!/bin/bash pwd ls echo "Report finished"O shebang seleciona o Bash quando o arquivo é executado diretamente. O comentário explica a tarefa, mas não é executado. O Bash executa
pwd,lseechonessa ordem. A terminação.shajuda o leitor a reconhecer o arquivo; ela não seleciona o interpretador. - 3DesafioVerifique o que seleciona a linguagem
Um colega altera a primeira linha para
#!/bin/she depois adiciona[[ ... ]]. O arquivo ainda termina em.sh. Por que ele pode falhar?---reveal---
O shebang seleciona
sh, que pode serdashe talvez não entenda[[ ... ]]do Bash. A extensão não escolhe a linguagem. Restaure um shebang Bash para recursos do Bash, com#!no início da primeira linha. - 4ExplicaçãoLeia o arquivo com o Bash primeiro
Execute
bash folder-report.sh. Isso inicia o Bash e passa a ele o arquivo de script legível; a permissão de execução no script não é necessária. O interpretador escolhido já é o Bash, portanto o shebang não faz essa escolha.Você deve ver um caminho, uma listagem e a mensagem “Report finished”. Os caminhos relativos usados pelos comandos dentro do script são resolvidos a partir de seu diretório de trabalho, não automaticamente da pasta do arquivo de script.
- 5ExemploPermita a execução direta
Adicione permissão de execução para o proprietário e execute o caminho exato:
chmod u+x folder-report.sh ./folder-report.sh./indica o diretório atual. A execução direta usa o shebang do arquivo. Se o arquivo for legível, mas não executável, o comando anterior combashpode funcionar enquanto este falha com “Permission denied.” A permissão e a seleção do interpretador são partes distintas da inicialização. - 6DicaEncontre o script pelo nome
Digitar
folder-report.shsem barra pede ao Bash que procure no PATH. O diretório atual normalmente não está nessa lista.Um diretório bin pessoal permite que você execute o script a partir de outras pastas quando ele está no PATH. Examine
echo "$PATH"e usecommand -v folder-report.shpara ver qual executável esse nome seleciona. Se uma cópia antiga vier primeiro no PATH, editar uma cópia mais recente em outro lugar não mudará o que esse nome executa. - 7DesafioMantenha uma mudança de diretório no shell certo
O script agora começa com
cd /var/log. Após o término de./folder-report.sh, seu terminal mudou para lá? Como um arquivo de configuração poderia mudá-lo?---reveal---
O script executado roda em um shell filho, portanto sua mudança de diretório não move o terminal pai. Executar um arquivo no shell atual com
source ./settings.shroda seus comandos nesse shell e pode mudar o diretório da sessão. Essa execução usa a linguagem do shell atual. - 8DesafioDiagnostique a inicialização antes de editar comandos
Um relatório legível funciona com
bash folder-report.sh. A execução direta informa “Permission denied”, e digitar apenas seu nome informa “command not found”. Quais dois problemas de inicialização devem ser verificados?---reveal---
Verifique a permissão de execução do script para a execução direta. Depois, verifique o PATH ou use o caminho explícito com
./para localizá-lo. Um shebang Bash válido seleciona o interpretador, mas não pode conceder permissões nem colocar o arquivo no PATH. - 9RecapitulaçãoUma inicialização envolve várias escolhas distintas
O arquivo contém a sequência de comandos. O interpretador lê sua linguagem, as permissões permitem a execução direta e o PATH ou uma barra localiza o arquivo.
Um script executado funciona em um shell filho. Um arquivo de configuração executado no shell atual funciona no shell já aberto, portanto suas atribuições e mudanças de diretório podem permanecer nessa sessão.
2Criar um nome de relatório com data sem perder espaços
11 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoAcompanhe um valor até um comando
- 2ExemploArmazene um destino com várias palavras
- 3ConexãoPasse a configuração a um processo filho
- 4DesafioSepare um nome de seu sufixo
- 5ExemploPreserve o caminho armazenado
- 6DesafioEscolha texto fixo ou texto variável
- 7ExemploCapture uma data para o nome
- 8ExemploCalcule antes de inserir o valor
- 9DesafioLocalize a fração perdida
- 10DesafioCombine o caminho e o valor capturado
- 11RecapitulaçãoDistinga as três funções
3Impedir que uma busca malsucedida resulte em um relatório bem-sucedido
10 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoTrate o resultado como parte da tarefa
- 2ExemploVeja a falha oculta no início do encadeamento
- 3Ideia-chaveFaça o encadeamento informar sua falha
- 4DesafioSalve o código que importa
- 5ExemploTrate explicitamente o trabalho malsucedido
- 6ExplicaçãoEscolha entre verificação de sintaxe e rastreamento de execução
- 7ExplicaçãoEntenda as opções de erro como controles separados
- 8DesafioExplique por que este script continua
- 9DesafioMantenha informado quem chamou o script
- 10RecapitulaçãoLeia tanto os dados quanto o resultado
4Inspecionar arquivos recebidos e ler seus registros
15 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoDeixe cada tipo de entrada escolher sua próxima etapa
- 2ExemploEscolha um teste para o tipo do caminho
- 3ExplicaçãoCompare valores da maneira adequada
- 4DesafioInterprete um teste de arquivo negado
- 5ExemploSelecione uma ação com o resultado de um comando
- 6DesafioAcompanhe limites sobrepostos
- 7ExplicaçãoAssocie uma palavra de ação com case
- 8ExemploForneça um arquivo por passagem a um laço com padrão
- 9DesafioExplique o caso da pasta vazia
- 10DicaEscolha um limite numérico variável
- 11ExemploLeia um registro sem separar seus espaços
- 12DesafioMantenha o último registro sem caractere de nova linha
- 13ConexãoAguarde sem verificar continuamente
- 14DesafioDiagnostique um total que permanece em zero
- 15RecapitulaçãoEscolha a estrutura adequada aos dados
5Aceitar arquivos de entrada e informar falhas parciais
10 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoFaça da entrada parte da chamada do comando
- 2ExemploInspecione os limites da chamada
- 3ExplicaçãoConsuma a opção inicial
- 4DesafioMantenha um argumento vazio na contagem
- 5ExemploRejeite uma chamada sem arquivos de entrada
- 6ExplicaçãoEscolha um valor padrão apenas para entrada opcional
- 7ExemploVerifique a própria operação de leitura
- 8DesafioLembre-se da falha anterior
- 9DesafioEncerre a análise antes de um nome de arquivo com hífen
- 10RecapitulaçãoDê aos comandos reutilizáveis um contrato confiável
6Agendar um relatório e verificar sua última execução
12 passos
Salve esta aula para seguir cada Lição Interativa passo a passo.
- 1IntroduçãoAgende apenas trabalhos com entrada completa
- 2ExemploLeia uma entrada de crontab pessoal
- 3DesafioAcompanhe um passo de minutos na mudança de hora
- 4DicaDê à tarefa um destino de saída
- 5ConexãoDistinga uma execução perdida de uma execução malsucedida
- 6ExemploColoque o trabalho em um serviço
- 7ExemploColoque o horário no temporizador correspondente
- 8ExplicaçãoCarregue as alterações e habilite o agendamento
- 9DesafioVerifique o resultado e também o próximo horário
- 10ExplicaçãoConte o tempo a partir de um evento quando necessário
- 11DesafioEscolha a recuperação após um período desligado
- 12RecapitulaçãoInspecione o agendamento e a tarefa separadamente
Questões de Scripts de shell
Conjunto 1: Acompanhar valores, registros e agendamentos10 Questões de Prática
Questão 1 de 10
/bin/bash^M: bad interpreter, mas /bin/bash existe. Qual alteração no arquivo resolve o problema indicado?Mostrar respostaOcultar resposta
^M indica um retorno de carro de terminadores de linha do Windows, fazendo o caminho do interpretador ser diferente de /bin/bash. Converter o arquivo para terminadores de linha do Unix remove esse caractere extra. A permissão de execução não corrige caracteres dentro do caminho do interpretador, e o PATH não resolve um caminho fixo no shebang.Questão 2 de 10
site?Mostrar respostaOcultar resposta
=. As aspas preservam as duas palavras como valor. Com espaços ao redor de =, o Bash trata site como um comando; sem aspas ao redor do valor, Hall se torna uma palavra de comando em vez de parte da atribuição.Questão 3 de 10
left=$(( 29 % 6 )) atribui?Mostrar respostaOcultar resposta
% retorna esse resto. O quociente 4 viria da divisão inteira com /, enquanto a aritmética do Bash não produz um quociente decimal como 4,83 a partir dessa expressão.Questão 4 de 10
done de fechamento em um script. Qual comando pode detectar esse problema de sintaxe sem executar o script?Mostrar respostaOcultar resposta
bash -n lê o script e verifica sua estrutura de shell sem executar os comandos. Ele pode detectar um laço sem o done de fechamento. bash -x também lê o script, mas o executa com rastreamento, portanto comandos válidos anteriores podem ser executados antes que o problema de sintaxe seja encontrado.Questão 5 de 10
[ 06 = 6 ] e [ 06 -eq 6 ], nessa ordem?Mostrar respostaOcultar resposta
Questão 6 de 10
a.csv e late batch.csv, ambos arquivos comuns. Quais valores são usados em for f in *.csv; do echo "$f"; done?Mostrar respostaOcultar resposta
"$f" entre aspas no corpo mantém esse valor junto quando ele é passado a um comando.Questão 7 de 10
Um arquivo contém oak, um caractere de nova linha e depois elm sem um caractere final de nova linha. Qual contagem é impressa?
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < trees.txt
echo "$count"
Mostrar respostaOcultar resposta
|| [ -n "$line" ] também processaria o registro final e produziria 2.Questão 8 de 10
./task.sh -v "blue room" output.txt, o script executa shift. Quais são agora os valores de $1 e $#?Mostrar respostaOcultar resposta
shift consome o primeiro argumento, “-v”, e desloca os dois argumentos restantes. O nome entre aspas se torna $1, e $# cai de 3 para 2. O espaço dentro do nome permanece intacto; o deslocamento não separa o texto nem consome também o segundo argumento.Questão 9 de 10
*/25 10-12 * * * é executado e quando ocorre sua última execução?Mostrar respostaOcultar resposta
Questão 10 de 10
inventory.timer?Mostrar respostaOcultar resposta
inventory.timer inicia inventory.service. O temporizador armazena o agendamento, enquanto o serviço define o trabalho. Acrescentar outra extensão ao nome completo do temporizador não identificaria a unidade correspondente padrão.Conjunto 2: Ler e executar pequenos scripts Bash10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
25 4 * * * /home/rae/bin/audit.sh especifica?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
[[ ... ]] do Bash, mas sua primeira linha é #!/bin/sh. Nesta máquina, sh é dash. Qual primeira linha seleciona o interpretador pretendido?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
label="west side", quais argumentos printf '<%s>\n' "$label" formata?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
file="shift notes.txt". Como ele deve copiar esse único arquivo para o diretório existente saved?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
archive existe e é um diretório. Quais são os resultados de [ -f archive ] e [ -d archive ], nessa ordem?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
O que é impresso por este código?
used=14
limit=20
percent=$(( used * 100 / limit ))
if [ "$percent" -ge 60 ]; then
used=$(( used + 2 ))
elif [ "$percent" -ge 70 ]; then
used=$(( used + 5 ))
fi
echo "$used"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
./label.sh "East Wing" report.txt. Quais são os valores de $# e $2?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
dir=${1:-/srv/logs}. Ele é chamado com um argumento que é uma string vazia entre aspas. Qual valor é atribuído?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 3: Acompanhar dados em um script completo10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
zone=west. O arquivo settings.sh contém apenas zone=east. O terminal executa bash settings.sh, depois source ./settings.sh e depois bash -c 'echo "${zone:-unset}"'. A variável nunca foi exportada. O que o último comando imprime?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
name=archive, o que echo "${name}_ready" imprime?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
completed=18 e total=32. Qual resultado inteiro é produzido por $(( completed * 100 / total ))?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O arquivo absent.log não existe. Qual código de saída chega a quem chamou o script?
#!/bin/bash
set -o pipefail
grep NOTICE absent.log | wc -l
status=$?
echo "Count ended"
exit "$status"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
O que é impresso por este script?
set -e
false || echo "Handled"
echo "Next"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
*) deve vir depois dos padrões de ações nomeadas?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O diretório atual contém apenas os arquivos comuns draft one.jpeg, final.jpeg e notes.txt. Qual é a saída?
count=0
for f in *.jpeg; do
[ "$f" = final.jpeg ] && continue
echo "${f%.jpeg}.jpg"
count=$(( count + 1 ))
done
echo "$count"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
until [ -f /tmp/upload.ready ]; do sleep 3; done. O arquivo comum já existe antes de o laço começar. Quantas vezes o corpo é executado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
status=0. Uma entrada inválida define status=1, e uma entrada posterior é processada com sucesso. Qual término informa que a solicitação ficou incompleta?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 4: Diagnosticar entradas, fluxo de execução e períodos desligados10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
weekly.sh para weekly, sem alterar seu conteúdo ou suas permissões. O que a perda da extensão faz com a escolha do interpretador pelo Linux com base no shebang?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
export REGION=north e depois inicia um script que atribui REGION=south e termina. Qual valor permanece no processo pai?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
pattern="*.txt". Qual argumento touch "$pattern" recebe?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
O que acontece neste script não interativo?
set -eu
dest=
if [ -z "$dest" ]; then
dest=${2:-/srv/archive}
fi
echo "$dest"
O script recebe apenas um argumento, input.txt.
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
A variável count contém 10, e o diretório atual permite gravação e não tem arquivo chamado 4. O que acontece?
if [ "$count" > 4 ]; then
echo "High"
else
echo "Low"
fi
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
case "$value" in [0-9]*) echo "Match" ;; *) echo "No" ;; esac. O que acontece para value=8draft?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
O que é impresso?
i=0
total=0
while [ "$i" -lt 4 ]; do
i=$(( i + 1 ))
[ "$i" -eq 2 ] && continue
total=$(( total + i ))
[ "$total" -gt 5 ] && break
done
echo "$i:$total"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
-v, uma string vazia entre aspas e "red room", nessa ordem. Ele executa shift e depois for arg in "$@"; do echo "<$arg>"; done. O que é impresso?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
0 11 9 * 2 /home/rae/bin/check.sh seleciona no cron comum?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
Persistent=true. Três ativações diárias passam enquanto o computador está desligado. Qual recuperação ele providencia quando é reativado?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Conjunto 5: Combinar proteção com aspas, verificações de falha e entradas reutilizáveis10 Questões de Prática
Salve esta aula para ver todas as respostas e praticar cada conjunto.
Questão 1 de 10
Um terminal Bash está em /home/rae, com PATH /home/rae/bin:/usr/local/bin:/usr/bin:/bin. Scripts Bash executáveis chamados scan existem nas duas pastas bin e no diretório atual. Cada um contém apenas um shebang Bash e cd /srv/cache; esse diretório existe e é acessível. Qual arquivo o primeiro comando executa e quais caminhos são impressos?
scan
pwd
source ./scan
pwd
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 2 de 10
a.txt e b.txt. Com as configurações padrão de separação e expansão de nomes de arquivo do Bash, quantos argumentos de dados são formatados por printf '<%s>\n' $value após value="*.txt spare"?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 3 de 10
ready na saída padrão e warning na saída de erro padrão e depois é bem-sucedido. O que é armazenado por message=$(the_command)?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 4 de 10
Qual código de saída chega a quem chamou o script?
#!/bin/bash
false
saved=$?
true && echo "Handled"
exit $(( saved + 2 ))
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 5 de 10
set -u e já atribuiu folder="". Ele deve parar com uma mensagem de diagnóstico útil antes de usar uma pasta ausente ou vazia. Qual expansão fornece essa verificação?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 6 de 10
"$text" tem comprimento diferente de zero?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 7 de 10
limit=3, quais valores são impressos por for i in {1..$limit}; do echo "$i"; done na expansão comum do Bash?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 8 de 10
Qual contagem é impressa com o comportamento padrão de encadeamentos do Bash? O arquivo contém três linhas terminadas por caracteres de nova linha.
count=5
cat tasks.txt | while IFS= read -r line; do
count=$(( count + 1 ))
done
count=$(( count + 2 ))
echo "$count"
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 9 de 10
Um script analisa suas entradas com este código e depois exige exatamente dois argumentos de arquivo. Após a chamada ./copy.sh -v -- "early notes.txt" -final.txt, quantos argumentos restam e o que deve acontecer em seguida?
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
--) shift; break ;;
-*) echo "Unknown option" >&2; exit 2 ;;
*) break ;;
esac
done
Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Questão 10 de 10
/home/rae/.local/bin. Qual alteração resolve a provável diferença?Mostrar respostaOcultar resposta
Salve esta aula para ver esta resposta.
Travou em uma questão sua? Ajuda com Tarefas
Termos-Chave
A
Ambiente mínimo
Anacron
Aspas duplas
echo "Home: $HOME *" permitem a expansão do caminho pessoal enquanto mantêm o asterisco.Aspas simples
echo '$HOME' imprimir os caracteres “$HOME” em vez de um caminho de diretório pessoal.Atribuição
name=value, sem espaços ao redor do sinal de igualdade.name="Lee Kim" mantém as duas palavras juntas como um valor armazenado.B
Bash
[[ ... ]] seleciona o Bash em seu shebang para que sua sintaxe condicional seja entendida.break
C
case
Código de saída
grep -q distingue uma correspondência, nenhuma correspondência e um problema ao ler a entrada.Código de saída do encadeamento
pipefail altere essa regra.grep falha, mas o wc seguinte conta com sucesso uma entrada vazia.Comentário
# no início de uma palavra fora de texto entre aspas.# Keep a copy for recovery explica por que a cópia de arquivo seguinte é necessária.Comparação de strings
Comparação numérica
-eq e -gt, independentemente do comprimento de seu texto.[ "$count" -ge 8 ] é bem-sucedida para uma contagem armazenada de 12.Contador
count=0 pode aumentar uma vez para cada linha que um laço lê.continue
cron
D
Diário de registros do systemd
journalctl -u backup.service mostra mensagens da tarefa de cópia de segurança.Divisão inteira
$(( 7 / 2 )) produzir 3, embora o quociente exato seja 3,5.E
elif
errexit
set -e do Bash, que encerra a execução em falhas não tratadas, permitindo contextos específicos que testam o código de saída de comandos.if malsucedida selecione seu ramo else em vez de encerrar o script.Execução no shell atual
./settings.sh com source carrega suas atribuições de variáveis diretamente na sessão Bash aberta.Execução por curto-circuito
&& ou || será executado.cd /data || exit 1 interrompe comandos dependentes após uma mudança de diretório malsucedida.exit
exit 2 após um erro de uso para que quem o chamou receba um resultado de falha.Expansão aritmética
$(( ... )) e insere o valor calculado no comando."$(( count + 1 ))" na próxima contagem inteira.Expansão de chaves
{1..5} antes de o Bash realizar a expansão de variáveis no comando.{1..$n} em um intervalo baseado no valor armazenado em n.Expansão de nomes de arquivo
*.log em nomes correspondentes separados antes de um laço for começar.Expansão de variável
"${file}_old" em “report_old” quando file contém “report”.Exportação de variável
F
Fim de arquivo
read do Bash informa falha ao encontrar essa condição.read informe falha.I
IFS
read preserva espaços em branco no início e no fim.IFS= read -r line mantém os espaços nas extremidades de cada registro lido do arquivo de entrada.Indicador de falha
Interpretador
#!/usr/bin/python3 lê código Python em vez de comandos Bash.Iteração
L
Laço for
web1 web2 db1 executa seu corpo uma vez para cada um dos três nomes de host.Laço until
Laço while
read chega ao fim do arquivo e informa falha.M
Mensagem de uso
N
Negação
[ ! -d "$p" ] aceita tanto um arquivo comum quanto um caminho que não existe.nounset
set -u do Bash, que trata a expansão de uma variável não definida como erro em um script não interativo.O
Opção
-v pode habilitar mensagens adicionais antes que o script processe os nomes de arquivo restantes.P
Padrão que corresponde a qualquer valor
* no final de um bloco case do Bash.*) informa comandos desconhecidos após a verificação dos subcomandos nomeados.Palavra-chave condicional
[[ do Bash, inicia uma estrutura de teste do shell com suas próprias regras de interpretação e correspondência de padrões.[[ permite usar [[ $name == *.log ]] sem separar o nome em palavras.Parâmetro posicional
$1, com chaves obrigatórias para posições após a nona.${10} recupera o décimo argumento sem acrescentar um zero a $1.Passo de agendamento do cron
*/45 no campo de minutos seleciona 0 e 45 e depois recomeça em 0 na hora seguinte.PATH
job.sh, mas segue o caminho explícito do diretório atual em ./job.sh.Permanência do gerenciador de usuário sem sessão ativa
Permissão de execução
chmod u+x job.sh permite que o proprietário tente executar ./job.sh.pipefail
grep pode fazer todo o encadeamento falhar.Processo filho
Proteção de caracteres com aspas ou escape
"$file" entre aspas preserva “monthly report.txt” como um argumento ao copiar o arquivo.Q
Quantidade de argumentos
$#, excluindo o nome usado na chamada../greet.sh Ana "Lee Kim" porque o nome entre aspas é um argumento.R
Ramo condicional
Rastreamento de execução
bash -x revela um argumento de origem vazio passado a um comando de cópia de arquivo.read
read -r -p "Name: " name solicita um nome e mantém as barras invertidas no texto digitado.Remoção de sufixo
${f%.jpeg}.Repasse de argumentos
"$@" para preservar os limites de cada um."$@" mantém uma entrada vazia e um nome com várias palavras como argumentos separados.Resto da divisão
%.$(( 17 % 5 )) é 2 porque três grupos completos de cinco usam 15.S
Saída de erro padrão
>&2 permanece visível quando a saída padrão vai para um arquivo.Script de shell
Separação de palavras
cp ser executado.Shebang
#! e indica o interpretador que o Linux deve usar para executar um script.#!/bin/bash começa no primeiro caractere, antes de qualquer comentário ou linha em branco.shift
-v, a próxima palavra da linha de comando se torna $1 para o analisador de opções.Substituição de comando
$(command).today=$(date +%F) captura uma data para uso no nome de um arquivo de cópia de segurança.T
Tabela de agendamento do cron
crontab -l exibe o crontab do usuário atual para que seus agendamentos possam ser inspecionados.Temporizador de calendário
OnCalendar=Mon..Fri 09:00 seleciona as manhãs dos dias úteis às 09:00.Temporizador monotônico
Terminador de linha
^M.Teste de arquivo
[ -d "$src" ] aceita um diretório de origem, mas rejeita um arquivo comum.Tratamento de sinais e eventos
U
Unidade de serviço
backup.service define o script ativado pelo temporizador de cópia de segurança correspondente.Unidade de temporizador
backup.timer estabelece o agendamento do serviço de cópia de segurança.V
Validação
Valor padrão
${1:-/var/log} para um argumento ausente ou vazio.Variável
city armazena “Lisbon” após city=Lisbon, portanto echo "$city" pode exibi-lo.Variável de ambiente
Verificação de sintaxe
bash -n detecta um done ausente antes que o laço possa executar comandos.Sobre esta aula
Crie seus próprios Materiais de Estudo
Transforme suas anotações, slides e documentos em Guias de Estudo, Questões de Prática, Flashcards e mais 6 ferramentas.