Ricerca nel sito web

Comprensione e apprendimento dello scripting di base della shell e della risoluzione dei problemi del file system Linux - Parte 10


La Linux Foundation ha lanciato la certificazione LFCS (Linux Foundation Certified Sysadmin), una nuovissima iniziativa il cui scopo è consentire a individui ovunque (e dovunque) di ottenere la certificazione nelle competenze da base a intermedia. supporto operativo per i sistemi Linux, che include il supporto di sistemi e servizi in esecuzione, insieme al monitoraggio e all'analisi generali, oltre a un processo decisionale intelligente quando si tratta di sollevare problemi ai team di supporto superiori.

Guarda il seguente video che ti guida in un'introduzione al programma di certificazione Linux Foundation.

Questo è l'ultimo articolo (Parte 10) della presente lunga serie di 10 tutorial. In questo articolo ci concentreremo sullo scripting di base della shell e sulla risoluzione dei problemi dei file system Linux. Entrambi gli argomenti sono richiesti per l'esame di certificazione LFCS.

Comprensione di terminali e shell

Chiariamo prima alcuni concetti.

  1. Una shell è un programma che prende comandi e li fornisce al sistema operativo affinché vengano eseguiti.
  2. Un terminale è un programma che consente a noi utenti finali di interagire con la shell. Un esempio di terminale è il terminale GNOME, come mostrato nell'immagine seguente.

Quando avviamo per la prima volta una shell, viene presentato un prompt dei comandi (noto anche come riga di comando), che ci dice che la shell è pronta per iniziare ad accettare comandi dal suo dispositivo di input standard, che di solito è la tastiera.

Potresti fare riferimento a un altro articolo di questa serie (Utilizzare il comando per creare, modificare e manipolare file – Parte 1) per rivedere alcuni comandi utili.

Linux fornisce una gamma di opzioni per le shell, le seguenti sono le più comuni:

bash Shell

Bash sta per Bourne Again SHell ed è la shell predefinita del progetto GNU. Incorpora funzionalità utili della shell Korn (ksh) e della shell C (csh), offrendo numerosi miglioramenti allo stesso tempo. Questa è la shell predefinita utilizzata dalle distribuzioni coperte dalla certificazione LFCS ed è la shell che utilizzeremo in questo tutorial.

sh Shell

La Bourne SHell è la shell più vecchia e quindi è stata per molti anni la shell predefinita di molti sistemi operativi simili a UNIX.

kshShell

La Korn SHell è una shell Unix sviluppata da David Korn presso i Bell Labs all'inizio degli anni '80. È retrocompatibile con la Bourne Shell e include molte funzionalità della C Shell.

Uno script di shell non è né più né meno che un file di testo trasformato in un programma eseguibile che combina i comandi che vengono eseguiti dalla shell uno dopo l'altro.

Script di shell di base

Come accennato in precedenza, uno script di shell nasce come un semplice file di testo. Pertanto, può essere creato e modificato utilizzando il nostro editor di testo preferito. Potresti prendere in considerazione l'utilizzo di vi/m (fai riferimento a Utilizzo dell'editor vi – Parte 2 di questa serie), che presenta l'evidenziazione della sintassi per tua comodità.

Digita il comando seguente per creare un file denominato myscript.sh e premi Invio.

vim myscript.sh

La primissima riga di uno script di shell deve essere la seguente (conosciuta anche come shebang).

#!/bin/bash

Esso “dice” al sistema operativo il nome dell'interprete che dovrà essere utilizzato per eseguire il testo che segue.

Ora è il momento di aggiungere i nostri comandi. Possiamo chiarire lo scopo di ciascun comando, o dell'intero script, aggiungendo anche commenti. Si noti che la shell ignora le righe che iniziano con il segno cancelletto # (commenti esplicativi).

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

Una volta scritto e salvato lo script, dobbiamo renderlo eseguibile.

chmod 755 myscript.sh

Prima di eseguire il nostro script, dobbiamo dire alcune parole sulla variabile d'ambiente ` PATH. Se corriamo,

echo $PATH

dalla riga di comando, vedremo il contenuto di ` PATH: un elenco di directory separate da due punti in cui vengono cercate quando inseriamo il nome di un programma eseguibile. Si chiama variabile d'ambiente perché fa parte dell'ambiente della shell, un insieme di informazioni che diventano disponibili per la shell e i suoi processi figli quando la shell viene avviata per la prima volta.

Quando digitiamo un comando e premiamo Invio, la shell cerca in tutte le directory elencate nella variabile ` PATH ed esegue la prima istanza che trova. Vediamo un esempio,

Se sono presenti due file eseguibili con lo stesso nome, uno in /usr/local/bin e un altro in /usr/bin, verrà eseguito quello nella prima directory prima, mentre l’altra verrà ignorata.

Se non abbiamo salvato il nostro script in una delle directory elencate nella variabile ` PATH, dobbiamo aggiungere ./ al nome del file per poter eseguire Esso. Altrimenti possiamo eseguirlo proprio come faremmo con un normale comando.

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

Condizionali

Ogni volta che è necessario specificare diverse azioni da intraprendere in uno script di shell, come risultato del successo o del fallimento di un comando, utilizzerai il costrutto if per definire tali condizioni. La sua sintassi di base è:

if CONDITION; then 
	COMMANDS;
else
	OTHER-COMMANDS 
fi

Dove CONDIZIONE può essere una delle seguenti (qui vengono citate solo le condizioni più frequenti) e restituisce vero quando:

  1. [ -a file ] → il file esiste.
  2. [ -d file ] → il file esiste ed è una directory.
  3. [ -f file ] →il file esiste ed è un file normale.
  4. [ -u file ] →il file esiste e il suo bit SUID (imposta ID utente) è impostato.
  5. [ -g file ] →il file esiste e il suo bit SGID è impostato.
  6. [ -k file ] →il file esiste e il suo sticky bit è impostato.
  7. [ -r file ] →il file esiste ed è leggibile.
  8. [ -s file ]→ il file esiste e non è vuoto.
  9. [ -w file ]→il file esiste ed è scrivibile.
  10. [ -x file ] è vero se il file esiste ed è eseguibile.
  11. [ stringa1=stringa2 ] → le stringhe sono uguali.
  12. [ stringa1 != stringa2 ] →le stringhe non sono uguali.

[ int1 op int2 ] dovrebbe far parte dell'elenco precedente, mentre gli elementi che seguono (ad esempio, -eq –> è vero se int1 è uguale a int2.) dovrebbe essere un elenco "figli" di [ int1 op int2 ] dove op è uno dei seguenti operatori di confronto.

  1. -eq –> è vero se int1 è uguale a int2.
  2. -ne –> vero se int1 non è uguale a int2.
  3. -lt –> vero se int1 è minore di int2.
  4. -le –> vero se int1 è minore o uguale a int2.
  5. -gt –> vero se int1 è maggiore di int2.
  6. -ge –> vero se int1 è maggiore o uguale a int2.

Per i loop

Questo ciclo consente di eseguire uno o più comandi per ciascun valore in un elenco di valori. La sua sintassi di base è:

for item in SEQUENCE; do 
		COMMANDS; 
done

Dove item è una variabile generica che rappresenta ciascun valore in SEQUENCE durante ogni iterazione.

Mentre i cicli

Questo ciclo consente di eseguire una serie di comandi ripetitivi purché il comando di controllo venga eseguito con uno stato di uscita pari a zero (con successo). La sua sintassi di base è:

while EVALUATION_COMMAND; do 
		EXECUTE_COMMANDS; 
done

Dove EVALUATION_COMMAND può essere qualsiasi comando che può terminare con uno stato riuscito (0) o fallito (diverso da 0) e EXECUTE_COMMANDS può essere qualsiasi programma, script o costrutto di shell, inclusi altri cicli nidificati.

Mettere tutto insieme

Dimostreremo l'uso del costrutto if e del ciclo for con il seguente esempio.

Determinare se un servizio è in esecuzione in una distribuzione basata su Systemd

Creiamo un file con l'elenco dei servizi che vogliamo monitorare a colpo d'occhio.

cat myservices.txt

sshd
mariadb
httpd
crond
firewalld

Il nostro script di shell dovrebbe assomigliare a.

#!/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

Spieghiamo come funziona lo script.

1). Il ciclo for legge il file myservices.txt un elemento di LIST alla volta. Quel singolo elemento è indicato dalla variabile generica denominata service. La LISTA è popolata con l'output di,

cat myservices.txt

2). Il comando precedente è racchiuso tra parentesi e preceduto da un simbolo di dollaro per indicare che dovrebbe essere valutato per popolare la LISTA su cui ripeteremo.

3). Per ogni elemento di LIST (ovvero ogni istanza della variabile di servizio), verrà eseguito il seguente comando.

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

Questa volta dobbiamo far precedere la nostra variabile generica (che rappresenta ogni elemento in LIST) con un segno di dollaro per indicare che è una variabile e quindi dovrebbe essere utilizzato il suo valore in ogni iterazione. L'output viene quindi reindirizzato a grep.

Il flag –quiet viene utilizzato per impedire a grep di visualizzare sullo schermo le righe in cui appare la parola running. Quando ciò accade, il comando precedente restituisce uno stato di uscita pari a 0 (rappresentato da $? nel costrutto if), verificando così che il servizio sia in esecuzione.

Uno stato di uscita diverso da 0 (che significa che la parola in esecuzione non è stata trovata nell'output di systemctl status $service) indica che il servizio non è corsa.

Potremmo fare un ulteriore passo avanti e verificare l'esistenza di myservices.txt prima ancora di tentare di accedere al ciclo 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
Eseguire il ping di una serie di host di rete o Internet per ottenere statistiche di risposta

Potresti voler mantenere un elenco di host in un file di testo e utilizzare uno script per determinare di tanto in tanto se sono pingabili o meno (sentiti libero di sostituire il contenuto di myhosts e provare tu stesso ).

Il comando integrato read shell dice al ciclo while di leggere myhosts riga per riga e assegna il contenuto di ciascuna riga alla variabile host, che viene poi passata al 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

Leggi anche:

  1. Impara lo scripting della shell: una guida dai principianti all'amministratore di sistema
  2. 5 script di shell per imparare a programmare la shell

Risoluzione dei problemi del file system

Sebbene Linux sia un sistema operativo molto stabile, se si blocca per qualche motivo (ad esempio, a causa di un'interruzione di corrente), uno (o più) dei file system non verranno smontati correttamente e quindi verranno automaticamente controllati gli errori quando Linux viene riavviato.

Inoltre, ogni volta che il sistema si avvia durante un avvio normale, controlla sempre l'integrità dei filesystem prima di montarli. In entrambi i casi questo viene eseguito utilizzando uno strumento chiamato fsck (“controllo del file system”).

fsck non solo controllerà l'integrità dei file system, ma tenterà anche di riparare i file system corrotti se richiesto di farlo. A seconda della gravità del danno, fsck potrebbe avere successo o meno; quando lo fa, le parti recuperate dei file vengono collocate nella directory lost+found, situata nella radice di ciascun file system.

Ultimo ma non meno importante, dobbiamo notare che potrebbero verificarsi incongruenze anche se proviamo a rimuovere un'unità USB mentre il sistema operativo sta ancora scrivendo su di essa, e potrebbero anche verificarsi danni all'hardware.

La sintassi di base di fsck è la seguente:

fsck [options] filesystem
Controllo della presenza di errori in un filesystem e tentativo di riparazione automatica

Per controllare un filesystem con fsck, dobbiamo prima smontarlo.

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

Oltre al flag -y, possiamo usare l'opzione -a per riparare automaticamente i file system senza fare domande e forzare il controllo anche quando il file system sembra pulito.

fsck -af /dev/sdg1

Se siamo interessati solo a scoprire cosa c'è che non va (senza provare a risolvere nulla per il momento) possiamo eseguire fsck con l'opzione -n, che restituirà i problemi del filesystem sullo standard output.

fsck -n /dev/sdg1

A seconda dei messaggi di errore nell'output di fsck, sapremo se possiamo provare a risolvere il problema da soli o inoltrarlo ai team di ingegneri per eseguire ulteriori controlli sull'hardware.

Riepilogo

Siamo arrivati alla fine di questa serie di 10 articoli in cui abbiamo cercato di coprire le competenze di dominio di base richieste per superare l'esame LFCS.

Per ovvi motivi, non è possibile coprire ogni singolo aspetto di questi argomenti in un singolo tutorial, ed è per questo che speriamo che questi articoli ti abbiano messo sulla strada giusta per provare tu stesso nuove cose e continuare ad imparare.

Se hai domande o commenti, sono sempre i benvenuti, quindi non esitare a scriverci tramite il modulo sottostante!