GNU/Linux >> Linux Esercitazione >  >> Linux

Trucchi Bash più stupidi:variabili, trova, descrittori di file e operazioni remote

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. ]


Linux
  1. Bash:uso procedurale sicuro per gli spazi bianchi di Trova nella selezione?

  2. Espansione e variabili Bash Brace?

  3. Come trovare il tipo di un file Img e montarlo?

  4. Trova un file con i comandi Trova e individua in Linux

  5. Thread e descrittori di file

Trova ed elimina il file più vecchio se ci sono più di X file in una directory in Linux

Plugin, suggerimenti e trucchi utili di Geany

Come utilizzare Sed per trovare e sostituire una stringa in un file

Modifica ricorsivamente le estensioni dei file in Bash

trova ed elimina file o cartelle più vecchi di x giorni

Cos'è esattamente <() in bash (e =() in zsh)?