GNU/Linux >> Linux Esercitazione >  >> Linux

Stupidi trucchi Bash:cronologia, riutilizzo di argomenti, file e directory, funzioni e altro ancora

In qualità di amministratore di sistema, le shell fanno parte delle operazioni quotidiane. Le shell spesso forniscono più opzioni e flessibilità rispetto a un'interfaccia utente grafica (GUI). Le attività ripetitive giornaliere possono essere facilmente automatizzate da script oppure è possibile programmare le attività per l'esecuzione in determinati momenti della giornata. Una shell fornisce un modo conveniente per interagire con il sistema e consente di fare di più in meno tempo. Esistono molte shell diverse, tra cui Bash, zsh, tcsh e PowerShell.

In questo post sul blog in due parti, condivido alcune battute di Bash che uso per velocizzare il mio lavoro e lasciare più tempo per bere un caffè. In questo post iniziale tratterò la cronologia, gli ultimi argomenti, il lavoro con file e directory, la lettura del contenuto dei file e le funzioni Bash. Nella seconda parte esaminerò le variabili della shell, il comando find, i descrittori di file e le operazioni di esecuzione in remoto.

Usa il comando cronologia

La history il comando è utile. History mi consente di vedere quali comandi ho eseguito su un particolare sistema o argomenti sono stati passati a quel comando. Uso history per eseguire nuovamente i comandi senza dover ricordare nulla.

Il record dei comandi recenti è memorizzato per impostazione predefinita in ~/.bash_history. Questa posizione può essere modificata modificando la variabile della shell HISTFILE. Esistono altre variabili, come HISTSIZE (righe da archiviare in memoria per la sessione corrente) e HISTFILESIZE (quante righe mantenere nel file di cronologia). Se vuoi saperne di più sulla history , vedi man bash .

Diciamo che eseguo il seguente comando:

$> sudo systemctl status sshd

Bash mi dice che il servizio sshd non è in esecuzione, quindi la prossima cosa che voglio fare è avviare il servizio. Ne avevo verificato lo stato con il mio comando precedente. Quel comando è stato salvato nella history , quindi posso fare riferimento. Corro semplicemente:

$> !!:s/status/start/
sudo systemctl start sshd

L'espressione di cui sopra ha il seguente contenuto:

  • !! - ripeti l'ultimo comando dalla cronologia
  • :s/status/start/ - sostituisci stato con inizio

Il risultato è che il servizio sshd viene avviato.

Successivamente, aumento il valore HISTSIZE predefinito da 500 a 5000 utilizzando il seguente comando:

$> echo “HISTSIZE=5000” >> ~/.bashrc && source ~/.bashrc

Cosa succede se voglio visualizzare gli ultimi tre comandi nella mia cronologia? Inserisco:

$> history 3
 1002  ls
 1003  tail audit.log
 1004  history 3

Eseguo tail su audit.log facendo riferimento al numero di riga della cronologia. In questo caso, utilizzo la riga 1003:

$> !1003
tail audit.log
..
..

Immagina di aver copiato qualcosa da un altro terminale o dal tuo browser e di incollare accidentalmente la copia (che hai nel buffer di copia) nel terminale. Quelle righe verranno archiviate nella cronologia, che qui è qualcosa che non vuoi. Ecco dove deseleziona HISTFILE &&esci torna utile

$> unset HISTFILE && exit

o

$> kill -9 $$

Fai riferimento all'ultimo argomento del comando precedente

Quando voglio elencare i contenuti delle directory per directory diverse, posso cambiare directory abbastanza spesso. C'è un bel trucco che puoi usare per fare riferimento all'ultimo argomento del comando precedente. Ad esempio:

$> pwd
/home/username/
$> ls some/very/long/path/to/some/directory
foo-file bar-file baz-file

Nell'esempio sopra, /some/very/long/path/to/some/directory è l'ultimo argomento del comando precedente.

Se voglio cd (cambia directory) in quella posizione, inserisco qualcosa del genere:

$> cd $_

$> pwd
/home/username/some/very/long/path/to/some/directory

Ora usa semplicemente un trattino per tornare a dove ero:

$> cd -
$> pwd
/home/username/

Lavora su file e directory

Immagina di voler creare una struttura di directory e spostare un gruppo di file con estensioni diverse in queste directory.

Innanzitutto, creo le directory in una volta sola:

$> mkdir -v dir_{rpm,txt,zip,pdf}
mkdir: created directory 'dir_rpm'
mkdir: created directory 'dir_txt'
mkdir: created directory 'dir_zip'
mkdir: created directory 'dir_pdf'

Successivamente, sposto i file in base all'estensione del file in ciascuna directory:

$> mv -- *.rpm dir_rpm/
$> mv -- *.pdf dir_pdf/
$> mv -- *.txt dir_txt/
$> mv -- *.zip dir_txt/

I caratteri a doppio trattino -- significa Fine delle Opzioni. Questo flag impedisce che i file che iniziano con un trattino vengano trattati come argomenti.

Successivamente, voglio sostituire/spostare tutti i file *.txt in file *.log, quindi inserisco:

$> for f in ./*.txt; do mv -v ”$file” ”${file%.*}.log”; done
renamed './file10.txt' -> './file10.log'
renamed './file1.txt' -> './file1.log'
renamed './file2.txt' -> './file2.log'
renamed './file3.txt' -> './file3.log'
renamed './file4.txt' -> './file4.log'

Invece di usare for ciclo sopra, posso installare il prename comandare e raggiungere l'obiettivo di cui sopra in questo modo:

$> prename -v 's/.txt/.log/' *.txt
file10.txt -> file10.log
file1.txt -> file1.log
file2.txt -> file2.log
file3.txt -> file3.log
file4.txt -> file4.log

Spesso, quando modifico un file di configurazione, eseguo una copia di backup di quello originale utilizzando un comando di copia di base. Ad esempio:

$> cp /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.back

Come puoi vedere, ripetere l'intero percorso e aggiungere .back al file non è così efficiente e probabilmente soggetto a errori. C'è un modo più breve e più ordinato per farlo. Eccolo:

$> cp /etc/sysconfig/network-scripts/ifcfg-eth0{,.back}

È possibile eseguire diversi controlli su file o variabili. Esegui help test per ulteriori informazioni.

Utilizzare il comando seguente per scoprire se un file è un collegamento simbolico:

$> [[ -L /path/to/file ]] && echo “File is a symlink”

Ecco un problema che ho riscontrato di recente. Volevo gunzippare/decomprimere un sacco di file in una volta sola. Senza pensare, ho digitato:

$> tar zxvf *.gz

Il risultato è stato:

tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors

I file tar erano:

iptables.tar.gz
openvpn.tar.gz
…..

Perché non ha funzionato e perché ls -l *.gz lavorare invece? Sotto il cofano, sembra così:

$> tar zxvf *.gz

Si trasforma come segue:

$> tar zxvf iptables.tar.gz openvpn.tar.gz
tar: openvpn.tar.gz: Not found in archive
tar: Exiting with failure status due to previous errors

Il tar comando dovrebbe trovare openvpn.tar.gz all'interno di iptables.tar.gz. L'ho risolto con un semplice for ciclo:

$> for f in ./*.gz; do tar zxvf "$f"; done
iptables.log
openvpn.log

Posso persino generare password casuali usando Bash! Ecco un esempio:

$> alphanum=( {a..z} {A..Z} {0..9} ); for((i=0;i<=${#alphanum[@]};i++)); do printf '%s' "${alphanum[@]:$((RANDOM%255)):1}"; done; echo

Ecco un esempio che utilizza OpenSSL:

$> openssl rand -base64 12
JdDcLJEAkbcZfDYQ

Leggi un file riga per riga

Supponiamo di avere un file con molti indirizzi IP e di voler operare su quegli indirizzi IP. Ad esempio, voglio eseguire dig per recuperare le informazioni sul DNS inverso per gli indirizzi IP elencati nel file. Voglio anche saltare gli indirizzi IP che iniziano con un commento (# o hashtag).

Userò fileA come esempio. I suoi contenuti sono:

10.10.12.13  some ip in dc1
10.10.12.14  another ip in dc2
#10.10.12.15 not used IP
10.10.12.16  another IP

Potrei copiare e incollare ogni indirizzo IP, quindi eseguire dig manualmente:

$> dig +short -x 10.10.12.13

Oppure potrei farlo:

$> while read -r ip _; do [[ $ip == \#* ]] && continue; dig +short -x "$ip"; done < ipfile

E se volessi scambiare le colonne nel fileA? Ad esempio, voglio inserire gli indirizzi IP nella colonna più a destra in modo che il fileA assomigli a questo:

some ip in dc1 10.10.12.13
another ip in dc2 10.10.12.14
not used IP #10.10.12.15
another IP 10.10.12.16

Corro:

$> while  read -r ip rest; do printf '%s %s\n' "$rest" "$ip"; done < fileA

Usa le funzioni Bash

Le funzioni in Bash sono diverse da quelle scritte in Python, C, awk o altri linguaggi. In Bash, una semplice funzione che accetta un argomento e stampa "Hello world" sarebbe simile a questa:

func() { local arg=”$1”; echo “$arg” ; }

Posso chiamare la funzione in questo modo:

$> func foo

A volte una funzione si richiama ricorsivamente per eseguire un determinato compito. Ad esempio:

func() { local arg="$@"; echo "$arg"; f "$arg"; }; f foo bar

Questa ricorsione durerà per sempre e utilizzerà molte risorse. In Bash, puoi usare FUNCNEST per limitare la ricorsione. Nell'esempio seguente, ho impostato FUNCNEST=5 per limitare la ricorsione a cinque.

func() { local arg="$@"; echo "$arg"; FUNCNEST=5; f "$arg"; }; f foo bar
foo bar
foo bar
foo bar
foo bar
foo bar
bash: f: maximum function nesting level exceeded (5)

Utilizzare una funzione per recuperare il file più recente o meno recente

Ecco una funzione di esempio per visualizzare il file più recente in una determinata directory:

latest_file()
{
  local f latest
  for f in "${1:-.}"/*
    do
      [[ $f -nt $latest ]] && latest="$f"
    done
   printf '%s\n' "$latest"
}

Questa funzione mostra il file più vecchio in una determinata directory:

oldest_file()
{
  local f oldest
  for file in "${1:-.}"/*
    do
      [[ -z $oldest || $f -ot $oldest ]] && oldest="$f"
    done
  printf '%s\n' "$oldest"
}

Questi sono solo alcuni esempi di come usare le funzioni in Bash senza invocare altri comandi esterni.

A volte mi ritrovo a digitare un comando più e più volte con molti parametri. Un comando che uso spesso è kubectl (CLI di Kubernetes). Sono stanco di eseguire questo lungo comando! Ecco il comando originale:

$> kubectl -n my_namespace get pods

o

$> kubectl -n my_namespace get rc,services

Questa sintassi mi richiede di includere manualmente -n my_namespace ogni volta che eseguo il comando. C'è un modo più semplice per farlo usando una funzione:

$> kubectl () { command kubectl -n my_namespace ”$@” ; }

Ora posso eseguire kubectl senza dover digitare -n namespace ogni volta:

$> kubectl get pods

Posso applicare la stessa tecnica ad altri comandi.

Concludi

Questi sono solo alcuni ottimi trucchi che esistono per Bash. Nella seconda parte, mostrerò altri esempi, incluso l'uso di trova e l'esecuzione remota. Ti incoraggio a mettere in pratica questi trucchi per rendere le tue attività di amministrazione della riga di comando più semplici e precise.

[ Corso online gratuito:panoramica tecnica di Red Hat Enterprise Linux. ]


Linux
  1. Trova file e directory in Linux come un professionista

  2. Come creare e chiamare funzioni in Bash

  3. Linux Elimina file e directory

  4. Rinomina file e directory in modo ricorsivo in ubuntu /bash

  5. Suggerimenti e trucchi preferiti per rsync

Come comprimere file e directory in Linux

Come sincronizzare file e directory utilizzando Zaloha.sh

Compressione e archiviazione di file e directory

Trova facilmente file e directory su Linux

File e directory predefiniti in cPanel

Come cancellare la cronologia di Bash in Linux e Mac