GNU/Linux >> Linux Esercitazione >  >> Linux

Come reindirizzare l'output del comando della shell

Gli script di shell forniscono una funzionalità molto potente:la possibilità di reindirizzare l'output da comandi e script e inviarlo a file, dispositivi o anche come input per altri comandi o script.

Questo articolo è incentrato sull'output di comandi e script.

Tipi di output

I comandi e gli script in una shell possono generare due tipi di output di base:

  • STDOUT: Il normale output di un comando/script (descrittore di file 1)
  • STDERR: L'output di errore da un comando/script (descrittore di file 2)

Per impostazione predefinita, STDOUT e STDERR vengono inviati allo schermo del tuo terminale.

In termini di input, STDIN per impostazione predefinita legge l'input dalla tastiera (descrittore di file 0). Un descrittore di file è un identificatore univoco per un file o un'altra risorsa I/O.

Come reindirizzare l'output della shell

Esistono diversi modi per reindirizzare l'output da script e comandi della shell.

1. Reindirizza STDOUT

Per i seguenti esempi, userò questo semplice insieme di file:

$ls -la file*
-rw-r--r--. 1 admin2 admin2  7 Mar 27 15:34 file1.txt
-rw-r--r--. 1 admin2 admin2 10 Mar 27 15:34 file2.txt
-rw-r--r--. 1 admin2 admin2 13 Mar 27 15:34 file3.txt

Sto eseguendo un semplice ls comandi per illustrare STDOUT e STDERR, ma lo stesso principio si applica alla maggior parte dei comandi che esegui da una shell.

Posso reindirizzare l'output standard a un file utilizzando ls file* > my_stdout.txt :

$ls file* > my_stdout.txt

$ cat my_stdout.txt 
file1.txt
file2.txt
file3.txt

Successivamente, eseguo un comando simile, ma con un 1 prima di > . Reindirizzamento utilizzando il > segnale è lo stesso dell'utilizzo di 1> per farlo:sto dicendo alla shell di reindirizzare lo STDOUT a quel file. Se ometto il descrittore di file, viene utilizzato STDOUT per impostazione predefinita. Posso dimostrarlo eseguendo sdiff comando per mostrare l'output di entrambi i comandi affiancati:

$ls file* 1> my_other_stdout.txt

$sdiff my_stdout.txt my_other_stdout.txt
file1.txt			             file1.txt
file2.txt			             file2.txt
file3.txt			             file3.txt

Come puoi vedere, entrambi gli output hanno lo stesso contenuto.

2. Reindirizza STDERR

Ora, cos'ha di speciale STDERR? Per dimostrare, introdurrò una condizione di errore nell'esempio precedente con ls file* non-existing-file* > my_normal_output.txt :

Ecco il risultato:

Immagine

Ecco alcune osservazioni dal test di cui sopra:

  1. L'output sui file esistenti viene inviato correttamente al file di destinazione.
  2. L'errore (che viene visualizzato quando provo a elencare qualcosa che non esiste) viene inviato allo schermo. Questo è il luogo predefinito in cui vengono inviati gli errori a meno che non vengano reindirizzati.

[ Scarica un cheat sheet per gli script di Bash Shell. ]

Successivamente, reindirizzerò l'output dell'errore facendo riferimento al descrittore di file 2 in modo esplicito con  ls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:

Immagine

Nell'esempio sopra:

  1. Il ls comando non visualizza il messaggio di errore sullo schermo come prima.
  2. L'output normale contiene ciò che mi aspetto.
  3. Il messaggio di errore viene inviato a my_error_output.txt file.

3. Invia STDOUT e STDERR allo stesso file

Un'altra situazione comune è inviare sia STDOUT che STDERR allo stesso file:

$ls file* non-existing-file* > my_consolidated_output.txt 2>&1

$ cat my_consolidated_output.txt 
ls: cannot access 'non-existing-file*': No such file or directory
file1.txt
file2.txt
file3.txt

In questo esempio, tutto l'output (normale ed errore) viene inviato allo stesso file.

Il 2>&1 costruzione significa "inviare lo STDERR allo stesso posto in cui stai inviando lo STDOUT ."

4. Reindirizza l'output, ma aggiungi il file

In tutti gli esempi precedenti, ogni volta che reindirizzavo un output, usavo un singolo > , che significa "invia qualcosa a questo file e avvia il file da zero ." Di conseguenza, se il file di destinazione esiste, viene sovrascritto.

Se voglio aggiungere in un file esistente, devo usare >> . Se il file non esiste già, verrà creato:

$echo "Adding stuff to the end of a file" >> my_output.txt

$cat my_output.txt 
file1.txt
file2.txt
file3.txt
Adding stuff to the end of a file

5. Reindirizzamento a un altro processo o da nessuna parte

Gli esempi precedenti riguardano il reindirizzamento dell'output a un file, ma puoi anche reindirizzare gli output ad altri processi o dev/null .

L'invio di output ad altri processi è una delle funzionalità più potenti di una shell. Per questa attività, usa il | simbolo (pipe), che invia l'output di un comando all'input del comando successivo:

ps -ef | grep chrome | grep -v grep | wc -l
21

L'esempio sopra elenca i miei processi, filtra quelli che contengono la stringa chrome , ignora la riga relativa al mio grep comando e conta le righe risultanti. Se voglio inviare l'output a un file, aggiungo > e un nome file alla fine della catena.

Infine, ecco un esempio in cui voglio ignorare uno degli output, lo STDERR:

$tar cvf my_files.tar file* more-non-existing*
file1.txt
file2.txt
file3.txt
tar: more-non-existing*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

Perché il tar comando non ha trovato alcun file con nomi che iniziano con more-non-existing , alla fine vengono visualizzati alcuni messaggi di errore.

Supponiamo che io crei degli script e non mi importi di vedere o catturare questi errori (lo so, nella vita reale, dovresti prevenire e gestire gli errori, non semplicemente ignorarli):

$tar cvf my_files.tar file* more-non-existing* 2> /dev/null
file1.txt
file2.txt
file3.txt

Il /dev/null è un file dispositivo speciale che è come un "buco nero":ciò che invii lì scompare.

[ Scarica questa guida all'installazione di applicazioni su Linux. ]

6. Usa il reindirizzamento in uno script

Immagine
=== SUMMARY OF INVESTIGATION OF chrome ===
Date/Time of the execution: 2022-03-25 18:05:50
Number of processes found.: 5
PIDs:
1245475
1249558
1316941
1382460
1384452

Questo script molto semplice esegue le seguenti operazioni:

  • Riga 3:esegue un comando nel sistema operativo e salva nella variabile DATE_TIME.
  • Riga 6:esegue ps comando e reindirizza a grep e in un file.
    • Invece di inviare l'output a un file, potrei inviarlo a una variabile (come nella riga 3), ma in questo caso voglio eseguire altre azioni usando lo stesso output, quindi lo acquisisco. In una situazione più realistica, avere il file potrebbe essere utile anche durante lo sviluppo o la risoluzione dei problemi, così posso indagare più facilmente su cosa genera il comando.
  • Riga 8:esegue comandi aggiuntivi, reindirizza gli output a wc e assegna il risultato a una variabile.
  • Riga 9:utilizza awk per selezionare solo la colonna 2 dall'output e ordinarla in ordine decrescente (solo per il gusto di aggiungere un'altra pipe).

Concludi

Questi erano alcuni esempi di reindirizzamento di STDOUT e STDERR. Mettendo tutto questo insieme, ti rendi conto di quanto possa essere potente il reindirizzamento. Concatenando i singoli comandi, manipolandone l'output e utilizzando il risultato come input per il comando successivo, è possibile eseguire attività che altrimenti potrebbero richiedere lo sviluppo di uno script o di un programma. Potresti anche incorporare la tecnica in altri script, usando tutto come elementi costitutivi.


Linux
  1. Come reindirizzare l'output su un file e stdout

  2. Come aggiungere l'output a un file?

  3. Come reindirizzare l'output di system() su un file?

  4. Come reindirizzare l'output del comando time su un file in Linux?

  5. Come salvare l'output di questo comando awk su file?

Come salvare l'output dei comandi in un file in Linux

Come salvare l'output dei comandi di Linux in un'immagine o in un file di testo

Reindirizzare tutto l'output su file usando Bash su Linux?

Come reindirizzare l'output del servizio systemd su un file

Come reindirizzare l'output del programma come input

Come reindirizzare l'output di un comando a un file quando il comando richiederà gli input dell'utente?