Questo post sul blog è il secondo di due che trattano alcuni suggerimenti e trucchi pratici per ottenere il massimo dalla shell Bash. Nella prima parte, ho trattato la cronologia, l'ultimo argomento, il lavoro con file e directory, la lettura di file e le funzioni Bash. In questo segmento, tratterò le variabili della shell, la ricerca, i descrittori di file e le operazioni remote.
Usa variabili shell
Le variabili Bash sono impostate dalla shell quando invocate. Perché dovrei usare hostname
quando posso usare $HOSTNAME, o perché dovrei usare whoami
quando posso usare $USER? Le variabili Bash sono molto veloci e non richiedono applicazioni esterne.
Queste sono alcune variabili usate di frequente:
$PATH
$HOME
$USER
$HOSTNAME
$PS1
..
$PS4
Usa l'echo
comando per espandere le variabili. Ad esempio, la variabile della shell $PATH può essere espansa eseguendo:
$> echo $PATH
[ Scarica ora:una guida per l'amministratore di sistema allo scripting Bash. ]
Usa il comando trova
Il find
command è probabilmente uno degli strumenti più utilizzati all'interno del sistema operativo Linux. È estremamente utile nelle shell interattive. Viene utilizzato anche negli script. Con find
Posso elencare file più vecchi o più recenti di una data specifica, eliminarli in base a tale data, modificare i permessi di file o directory e così via.
Acquistiamo maggiore familiarità con questo comando.
Per elencare i file più vecchi di 30 giorni, eseguo semplicemente:
$> find /tmp -type f -mtime +30
Per eliminare i file più vecchi di 30 giorni, esegui:
$> find /tmp -type f -mtime +30 -exec rm -rf {} \;
o
$> find /tmp -type f -mtime +30 -exec rm -rf {} +
Mentre i comandi precedenti elimineranno i file più vecchi di 30 giorni, come scritto, biforcano il rm
comando ogni volta che trovano un file. Questa ricerca può essere scritta in modo più efficiente utilizzando xargs
:
$> find /tmp -name '*.tmp' -exec printf '%s\0' {} \; | xargs -0 rm
Posso usare find
per elencare sha256sum
file solo eseguendo:
$> find . -type f -exec sha256sum {} +
E ora per cercare ed eliminare i file .jpg duplicati:
$> find . -type f -name '*.jpg' -exec sha256sum {} + | sort -uk1,1
Descrittori di file di riferimento
Nella shell Bash, i descrittori di file (FD) sono importanti nella gestione dell'input e dell'output dei comandi. Molte persone hanno problemi a comprendere correttamente i descrittori di file. Ogni processo ha tre descrittori di file predefiniti, vale a dire:
Codice | Significato | Posizione | Descrizione |
---|---|---|---|
0 | Input standard | /dev/stdin | Tastiera, file o stream |
1 | Uscita standard | /dev/stdout | Monitoraggio, terminale, display |
2 | Errore standard | /dev/stderr | I codici di uscita diversi da zero sono generalmente>FD2, display |
Ora che sai cosa fanno gli FD predefiniti, vediamoli in azione. Comincio creando una directory chiamata foo
, che contiene file1
.
$> ls foo/ bar/
ls: cannot access 'bar/': No such file or directory
foo/:
file1
L'output Nessun file o directory di questo tipo va a Errore standard (stderr) e viene visualizzato anche sullo schermo. Eseguirò lo stesso comando, ma questa volta userò 2>
per omettere stderr:
$> ls foo/ bar/ 2>/dev/null
foo/:
file1
È possibile inviare l'output di foo
allo Standard Output (stdout) e a un file contemporaneamente e ignorare stderr. Ad esempio:
$> { ls foo bar | tee -a ls_out_file ;} 2>/dev/null
foo:
file1
Quindi:
$> cat ls_out_file
foo:
file1
Il comando seguente invia stdout a un file e stderr a /dev/null
in modo che l'errore non venga visualizzato sullo schermo:
$> ls foo/ bar/ >to_stdout 2>/dev/null
$> cat to_stdout
foo/:
file1
Il comando seguente invia stdout e stderr allo stesso file:
$> ls foo/ bar/ >mixed_output 2>&1
$> cat mixed_output
ls: cannot access 'bar/': No such file or directory
foo/:
file1
Questo è ciò che è successo nell'ultimo esempio, in cui stdout e stderr sono stati reindirizzati allo stesso file:
ls foo/ bar/ >mixed_output 2>&1
| |
| Redirect stderr to where stdout is sent
|
stdout is sent to mixed_output
Un altro trucco breve (> Bash 4.4) per inviare sia stdout che stderr allo stesso file utilizza il segno e commerciale. Ad esempio:
$> ls foo/ bar/ &>mixed_output
Ecco un reindirizzamento più complesso:
exec 3>&1 >write_to_file; echo "Hello World"; exec 1>&3 3>&-
Questo è ciò che accade:
- exec 3>&1 Copia lo stdout nel descrittore di file 3
- > write_to_file Fai in modo che FD 1 scriva nel file
- echo "Hello World" Vai al file perché FD 1 ora punta al file
- exec 1>&3 Copia FD 3 su 1 (scambia)
- Tre>&- Chiudi il descrittore di file tre (non ne abbiamo più bisogno)
Spesso è utile raggruppare i comandi e quindi inviare l'output standard a un singolo file. Ad esempio:
$> { ls non_existing_dir; non_existing_command; echo "Hello world"; } 2> to_stderr
Hello world
Come puoi vedere, sullo schermo viene stampato solo "Hello world", ma l'output dei comandi non riusciti viene scritto nel file to_stderr.
Esegui operazioni remote
Uso Telnet, netcat, Nmap e altri strumenti per verificare se un servizio remoto è attivo e se posso connettermi ad esso. Questi strumenti sono utili, ma non sono installati per impostazione predefinita su tutti i sistemi.
Fortunatamente, esiste un modo semplice per testare una connessione senza utilizzare strumenti esterni. Per vedere se un server remoto esegue un Web, database, SSH o qualsiasi altro servizio, eseguire:
$> timeout 3 bash -c ‘</dev/tcp/remote_server/remote_port’ || echo “Failed to connect”
Ad esempio, per vedere se serverA sta eseguendo il servizio MariaDB:
$> timeout 3 bash -c ‘</dev/tcp/serverA/3306’ || echo “Failed to connect”
Se la connessione non riesce, viene visualizzato il messaggio Impossibile connettersi messaggio viene visualizzato sullo schermo.
Si supponga serverA è dietro un firewall/NAT. Voglio vedere se il firewall è configurato per consentire una connessione al database al serverA , ma non ho ancora installato un server di database. Per emulare una porta del database (o qualsiasi altra porta), posso usare quanto segue:
[serverA ~]# nc -l 3306
Su clienteA , esegui:
[clientA ~]# timeout 3 bash -c ‘</dev/tcp/serverA/3306’ || echo “Failed”
Mentre sto discutendo di connessioni remote, che dire dell'esecuzione di comandi su un server remoto su SSH? Posso usare il seguente comando:
$> ssh remotehost <<EOF # Press the Enter key here
> ls /etc
EOF
Questo comando esegue ls /etc
sull'host remoto.
Posso anche eseguire uno script locale sull'host remoto senza dover copiare lo script sul server remoto. Un modo è inserire:
$> ssh remote_host 'bash -s' < local_script
Un altro esempio consiste nel passare le variabili di ambiente localmente al server remoto e terminare la sessione dopo l'esecuzione.
$> exec ssh remote_host ARG1=FOO ARG2=BAR 'bash -s' <<'EOF'
> printf %s\\n "$ARG1" "$ARG2"
> EOF
Password:
FOO
BAR
Connection to remote_host closed.
Ci sono molte altre azioni complesse che posso eseguire sull'host remoto.
Concludi
C'è sicuramente di più in Bash di quanto sono stato in grado di coprire in questo post sul blog in due parti. Condivido ciò che so e di cui mi occupo quotidianamente. L'idea è di familiarizzare con alcune tecniche che potrebbero rendere il tuo lavoro meno soggetto a errori e più divertente.
[ Vuoi testare le tue capacità di amministratore di sistema? Fai una valutazione delle abilità oggi. ]