Pesquisa de site

Compreendendo e aprendendo scripts básicos de shell e solução de problemas do sistema de arquivos Linux - Parte 10


A Linux Foundation lançou a certificação LFCS (Linux Foundation Certified Sysadmin), uma iniciativa totalmente nova cujo objetivo é permitir que indivíduos de qualquer lugar (e em qualquer lugar) obtenham certificação em nível básico a intermediário. suporte operacional para sistemas Linux, que inclui suporte a sistemas e serviços em execução, juntamente com monitoramento e análise geral, além de tomada de decisão inteligente quando se trata de levantar questões às equipes de suporte superiores.

Confira o vídeo a seguir que apresenta uma introdução ao Programa de Certificação Linux Foundation.

Este é o último artigo (Parte 10) da longa série de 10 tutoriais. Neste artigo, nos concentraremos em scripts básicos de shell e na solução de problemas de sistemas de arquivos Linux. Ambos os tópicos são obrigatórios para o exame de certificação LFCS.

Noções básicas sobre terminais e shells

Vamos esclarecer alguns conceitos primeiro.

  1. Um shell é um programa que recebe comandos e os fornece ao sistema operacional para serem executados.
  2. Um terminal é um programa que nos permite, como usuários finais, interagir com o shell. Um exemplo de terminal é o terminal GNOME, conforme mostrado na imagem abaixo.

Quando iniciamos um shell pela primeira vez, ele apresenta um prompt de comando (também conhecido como linha de comando), que nos informa que o shell está pronto para começar a aceitar comandos de seu dispositivo de entrada padrão, que geralmente é o teclado.

Você pode consultar outro artigo desta série (Usar comando para criar, editar e manipular arquivos – Parte 1) para revisar alguns comandos úteis.

O Linux oferece uma variedade de opções de shells, sendo as seguintes as mais comuns:

bash Concha

Bash significa Bourne Again SHell e é o shell padrão do Projeto GNU. Ele incorpora recursos úteis do shell Korn (ksh) e do shell C (csh), oferecendo várias melhorias ao mesmo tempo. Este é o shell padrão usado pelas distribuições cobertas pela certificação LFCS e é o shell que usaremos neste tutorial.

concha

O Bourne SHell é o shell mais antigo e, portanto, tem sido o shell padrão de muitos sistemas operacionais do tipo UNIX por muitos anos.

Concha ksh

O Korn SHell é um shell Unix que foi desenvolvido por David Korn no Bell Labs no início dos anos 1980. É compatível com versões anteriores do shell Bourne e inclui muitos recursos do shell C.

Um script de shell nada mais é do que um arquivo de texto transformado em um programa executável que combina comandos que são executados pelo shell um após o outro.

Script básico de shell

Conforme mencionado anteriormente, um script de shell nasce como um arquivo de texto simples. Assim, pode ser criado e editado usando nosso editor de texto preferido. Você pode considerar usar vi/m (consulte Uso do Editor vi – Parte 2 desta série), que apresenta realce de sintaxe para sua conveniência.

Digite o seguinte comando para criar um arquivo chamado myscript.sh e pressione Enter.

vim myscript.sh

A primeira linha de um script de shell deve ser a seguinte (também conhecida como shebang).

#!/bin/bash

Ele “informa” ao sistema operacional o nome do interpretador que deve ser usado para executar o texto a seguir.

Agora é hora de adicionar nossos comandos. Podemos esclarecer o propósito de cada comando, ou de todo o script, adicionando também comentários. Observe que o shell ignora as linhas que começam com um sinal de cerquilha # (comentários explicativos).

#!/bin/bash
echo This is Part 10 of the 10-article series about the LFCS certification
echo Today is $(date +%Y-%m-%d)

Depois que o script for escrito e salvo, precisamos torná-lo executável.

chmod 755 myscript.sh

Antes de executar nosso script, precisamos dizer algumas palavras sobre a variável de ambiente ` PATH. Se corrermos,

echo $PATH

na linha de comando, veremos o conteúdo de ` PATH: uma lista separada por dois pontos de diretórios que são pesquisados quando inserimos o nome de um programa executável. Ela é chamada de variável de ambiente porque faz parte do ambiente shell – um conjunto de informações que se torna disponível para o shell e seus processos filhos quando o shell é iniciado pela primeira vez.

Quando digitamos um comando e pressionamos Enter, o shell pesquisa em todos os diretórios listados na variável ` PATH e executa a primeira instância encontrada. Vejamos um exemplo,

Se houver dois arquivos executáveis com o mesmo nome, um em /usr/local/bin e outro em /usr/bin, o que estiver no primeiro diretório será executado primeiro, enquanto o outro será desconsiderado.

Se não salvamos nosso script dentro de um dos diretórios listados na variável ` PATH, precisamos anexar ./ ao nome do arquivo para executar isto. Caso contrário, podemos executá-lo como faríamos com um comando normal.

pwd
./myscript.sh
cp myscript.sh ../bin
cd ../bin
pwd
myscript.sh

Condicionais

Sempre que você precisar especificar diferentes cursos de ação a serem executados em um shell script, como resultado do sucesso ou falha de um comando, você usará a construção if para definir tais condições. Sua sintaxe básica é:

if CONDITION; then 
	COMMANDS;
else
	OTHER-COMMANDS 
fi

Onde CONDITION pode ser um dos seguintes (apenas as condições mais frequentes são citadas aqui) e é avaliado como verdadeiro quando:

  1. [ -a arquivo ] → arquivo existe.
  2. [ -d arquivo] → arquivo existe e é um diretório.
  3. [ -f arquivo ] →arquivo existe e é um arquivo normal.
  4. [ -u arquivo ] →arquivo existe e seu bit SUID (definir ID do usuário) está definido.
  5. [ -g arquivo ] →arquivo existe e seu bit SGID está definido.
  6. [ -k arquivo ] →arquivo existe e seu sticky bit está definido.
  7. [ -r arquivo ] →arquivo existe e é legível.
  8. [ -s arquivo ]→ arquivo existe e não está vazio.
  9. [ -w arquivo ]→arquivo existe e é gravável.
  10. [ -x file ] é verdadeiro se o arquivo existir e for executável.
  11. [ string1=string2 ] → as strings são iguais.
  12. [ string1 != string2 ] →as strings não são iguais.

[ int1 op int2 ] deve fazer parte da lista anterior, enquanto os itens a seguir (por exemplo, -eq –> são verdadeiros se int1 é igual a int2.) deve ser uma lista “filhos” de [ int1 op int2 ] onde op é um dos seguintes operadores de comparação.

  1. -eq –> é verdadeiro se int1 for igual a int2.
  2. -ne –> verdadeiro se int1 não for igual a int2.
  3. -lt –> verdadeiro se int1 for menor que int2.
  4. -le –> verdadeiro se int1 for menor ou igual a int2.
  5. -gt –> verdadeiro se int1 for maior que int2.
  6. -ge –> verdadeiro se int1 for maior ou igual a int2.

Para loops

Este loop permite executar um ou mais comandos para cada valor de uma lista de valores. Sua sintaxe básica é:

for item in SEQUENCE; do 
		COMMANDS; 
done

Onde item é uma variável genérica que representa cada valor em SEQUENCE durante cada iteração.

Enquanto Loops

Este loop permite executar uma série de comandos repetitivos desde que o comando de controle seja executado com status de saída igual a zero (com sucesso). Sua sintaxe básica é:

while EVALUATION_COMMAND; do 
		EXECUTE_COMMANDS; 
done

Onde EVALUATION_COMMAND pode ser qualquer comando(s) que possa(m) sair com status de sucesso (0) ou falha (diferente de 0) e EXECUTE_COMMANDS pode ser qualquer programa, script ou construção de shell, incluindo outros loops aninhados.

Juntando tudo

Demonstraremos o uso da construção if e do loop for com o exemplo a seguir.

Determinando se um serviço está sendo executado em uma distribuição baseada em systemd

Vamos criar um arquivo com uma lista de serviços que queremos monitorar rapidamente.

cat myservices.txt

sshd
mariadb
httpd
crond
firewalld

Nosso script de shell deve ser parecido.

#!/bin/bash

This script iterates over a list of services and
is used to determine whether they are running or not.

for service in $(cat myservices.txt); do
    	systemctl status $service | grep --quiet "running"
    	if [ $? -eq 0 ]; then
            	echo $service "is [ACTIVE]"
    	else
            	echo $service "is [INACTIVE or NOT INSTALLED]"
    	fi
done

Vamos explicar como o script funciona.

1). O loop for lê o arquivo myservices.txt, um elemento de LIST por vez. Esse único elemento é denotado pela variável genérica chamada serviço. A LIST é preenchida com a saída de,

cat myservices.txt

2). O comando acima está entre parênteses e precedido por um cifrão para indicar que ele deve ser avaliado para preencher a LISTA sobre a qual iremos iterar.

3). Para cada elemento de LIST (ou seja, cada instância da variável de serviço), o seguinte comando será executado.

systemctl status $service | grep --quiet "running"

Desta vez precisamos preceder nossa variável genérica (que representa cada elemento em LIST) com um cifrão para indicar que é uma variável e, portanto, seu valor em cada iteração deve ser usado. A saída é então canalizada para grep.

A flag –quiet é usada para evitar que grep exiba na tela as linhas onde a palavra running aparece. Quando isso acontece, o comando acima retorna um status de saída 0 (representado por $? na construção if), verificando assim se o serviço está em execução.

Um status de saída diferente de 0 (significando que a palavra em execução não foi encontrada na saída de systemctl status $service) indica que o serviço não está correndo.

Poderíamos dar um passo adiante e verificar a existência de myservices.txt antes mesmo de tentar entrar no loop for.

#!/bin/bash

This script iterates over a list of services and
is used to determine whether they are running or not.

if [ -f myservices.txt ]; then
    	for service in $(cat myservices.txt); do
            	systemctl status $service | grep --quiet "running"
            	if [ $? -eq 0 ]; then
                    	echo $service "is [ACTIVE]"
            	else
                    	echo $service "is [INACTIVE or NOT INSTALLED]"
            	fi
    	done
else
    	echo "myservices.txt is missing"
fi
Executando ping em uma série de hosts de rede ou Internet para obter estatísticas de resposta

Você pode querer manter uma lista de hosts em um arquivo de texto e usar um script para determinar de vez em quando se eles são pingáveis ou não (sinta-se à vontade para substituir o conteúdo de myhosts e tentar você mesmo ).

O comando interno read shell diz ao loop while para ler myhosts linha por linha e atribui o conteúdo de cada linha à variável host, que é então passada para o comando ping.

#!/bin/bash

This script is used to demonstrate the use of a while loop

while read host; do
    	ping -c 2 $host
done < myhosts

Leia também:

  1. Aprenda Shell Scripting: um guia para iniciantes e administradores de sistema
  2. 5 scripts Shell para aprender programação Shell

Solução de problemas do sistema de arquivos

Embora o Linux seja um sistema operacional muito estável, se ele travar por algum motivo (por exemplo, devido a uma queda de energia), um (ou mais) dos seus sistemas de arquivos não será desmontado corretamente e, portanto, será verificado automaticamente em busca de erros quando o Linux é reiniciado.

Além disso, cada vez que o sistema inicializa durante uma inicialização normal, ele sempre verifica a integridade dos sistemas de arquivos antes de montá-los. Em ambos os casos, isso é realizado usando uma ferramenta chamada fsck (“verificação do sistema de arquivos”).

O fsck não apenas verificará a integridade dos sistemas de arquivos, mas também tentará reparar sistemas de arquivos corrompidos se for instruído a fazê-lo. Dependendo da gravidade do dano, o fsck pode ter sucesso ou não; quando isso acontece, as partes recuperadas dos arquivos são colocadas no diretório lost+found, localizado na raiz de cada sistema de arquivos.

Por último, mas não menos importante, devemos observar que inconsistências também podem acontecer se tentarmos remover uma unidade USB enquanto o sistema operacional ainda estiver gravando nela, podendo até resultar em danos ao hardware.

A sintaxe básica do fsck é a seguinte:

fsck [options] filesystem
Verificando erros em um sistema de arquivos e tentando reparar automaticamente

Para verificar um sistema de arquivos com fsck, devemos primeiro desmontá-lo.

mount | grep sdg1
umount /mnt
fsck -y /dev/sdg1

Além do sinalizador -y, podemos usar a opção -a para reparar automaticamente os sistemas de arquivos sem fazer perguntas e forçar a verificação mesmo quando o sistema de arquivos parecer limpo.

fsck -af /dev/sdg1

Se estivermos interessados apenas em descobrir o que está errado (sem tentar consertar nada por enquanto), podemos executar o fsck com a opção -n, que exibirá os problemas do sistema de arquivos na saída padrão.

fsck -n /dev/sdg1

Dependendo das mensagens de erro na saída do fsck, saberemos se podemos tentar resolver o problema sozinhos ou encaminhá-lo para as equipes de engenharia para realizarem verificações adicionais no hardware.

Resumo

Chegamos ao final desta série de 10 artigos onde tentamos cobrir as competências básicas de domínio necessárias para passar no exame LFCS.

Por razões óbvias, não é possível cobrir todos os aspectos desses tópicos em um único tutorial, e é por isso que esperamos que esses artigos tenham colocado você no caminho certo para experimentar coisas novas e continuar aprendendo.

Se você tiver alguma dúvida ou comentário, eles serão sempre bem-vindos – então não hesite em nos enviar uma mensagem através do formulário abaixo!