Zoeken…


Syntaxis

  • commando </ pad / naar / bestand # Standaardinvoer omleiden naar bestand
  • commando> / pad / naar / bestand # Leid standaarduitvoer naar flie
  • commando file_descriptor> / path / to / file # Stuur de output van file_descriptor door naar het bestand
  • commando> & file_descriptor # Uitvoer omleiden naar file_descriptor
  • opdracht file_descriptor> & another_file_descriptor # Stuur file_descriptor door naar another_file_descriptor
  • commando <& file_descriptor # Stuur file_descriptor door naar standaard invoer
  • opdracht &> / pad / naar / bestand # Standaarduitvoer en standaardfout naar bestand omleiden

parameters

Parameter Details
interne bestandsdescriptor Een geheel getal.
richting Een van > , < of <>
externe bestandsdescriptor of pad & gevolgd door een geheel getal voor bestandsdescriptor of een pad.

Opmerkingen

UNIX-consoleprogramma's hebben een invoerbestand en twee uitvoerbestanden (invoer- en uitvoerstromen, evenals apparaten, worden door het besturingssysteem als bestanden behandeld.) Dit zijn meestal het toetsenbord en het scherm, maar alle of alle kunnen worden omgeleid om van - of naar - een bestand of ander programma te komen.

STDIN is standaardinvoer en is hoe het programma interactieve invoer ontvangt. STDIN krijgt meestal de bestandsbeschrijving 0 toegewezen.

STDOUT is standaarduitvoer. Wat wordt uitgezonden op STDOUT wordt beschouwd als het "resultaat" van het programma. STDOUT krijgt meestal bestandsbeschrijving 1 toegewezen.

STDERR is waar foutmeldingen worden weergegeven. Wanneer u een programma uitvoert vanaf de console, wordt STDERR op het scherm weergegeven en is het niet te onderscheiden van STDOUT . STDERR krijgt meestal de bestandsbeschrijving 2 toegewezen.

De volgorde van omleiding is belangrijk

command > file 2>&1

STDERR zowel ( STDOUT als STDERR ) naar het bestand STDERR .

command 2>&1 > file

Hiermee wordt alleen STDOUT omgeleid, omdat de bestandsdescriptor 2 wordt omgeleid naar het bestand waarnaar wordt verwezen door bestandsdescriptor 1 (wat nog niet het file is wanneer de instructie wordt geëvalueerd).

Elk commando in een pijplijn heeft zijn eigen STDERR (en STDOUT ) omdat elk een nieuw proces is. Dit kan verrassende resultaten opleveren als u verwacht dat een omleiding de hele pijplijn zal beïnvloeden. Bijvoorbeeld deze opdracht (verpakt voor leesbaarheid):

$ python -c 'import sys;print >> sys.stderr, "Python error!"' \
| cut -f1 2>> error.log

zal "Python error!" afdrukken naar de console in plaats van het logboekbestand. Voeg in plaats daarvan de fout toe aan de opdracht die u wilt vastleggen:

$ python -c 'import sys;print >> sys.stderr, "Python error!"' 2>> error.log \
| cut -f1 

Standaarduitvoer omleiden

> stuur de standaarduitvoer (ook bekend als STDOUT ) van de huidige opdracht om naar een bestand of een andere descriptor.

Deze voorbeelden schrijven de uitvoer van de opdracht ls in het bestand file.txt

ls >file.txt
> file.txt ls

Het doelbestand wordt gemaakt als het niet bestaat, anders wordt dit bestand afgekapt.

De standaardomleidingsbeschrijving is de standaarduitvoer of 1 als er geen is opgegeven. Deze opdracht is gelijk aan de vorige voorbeelden, waarbij de standaarduitvoer expliciet is aangegeven:

ls 1>file.txt

Opmerking: de omleiding wordt geïnitialiseerd door de uitgevoerde shell en niet door de uitgevoerde opdracht, daarom wordt dit gedaan vóór de uitvoering van de opdracht.

STDIN omleiden

< leest uit zijn rechterargument en schrijft naar zijn linkerargument.

Om een bestand te schrijven naar STDIN we moeten lezen /tmp/a_file en schrijven in STDIN dwz 0</tmp/a_file

Opmerking: Interne bestandsdescriptor staat standaard op 0 ( STDIN ) voor <

$ echo "b" > /tmp/list.txt
$ echo "a" >> /tmp/list.txt
$ echo "c" >> /tmp/list.txt
$ sort < /tmp/list.txt
a
b
c

Zowel STDOUT als STDERR omleiden

Bestandsdescriptors zoals 0 en 1 zijn pointers. We veranderen waar bestandsomschrijvingen naar verwijzen met omleiding. >/dev/null betekent 1 punt naar /dev/null .

Eerst wijzen we 1 ( STDOUT ) naar /dev/null vervolgens punt 2 ( STDERR ) naar STDERR 1 STDERR .

# STDERR is redirect to STDOUT: redirected to /dev/null,
# effectually redirecting both STDERR and STDOUT to /dev/null
echo 'hello' > /dev/null 2>&1
4.0

Dit kan verder worden ingekort tot het volgende:

echo 'hello' &> /dev/null

Deze vorm kan echter ongewenst zijn in productie als shell-compatibiliteit een probleem is omdat het conflicteert met POSIX, parsing-dubbelzinnigheid introduceert en shells zonder deze functie het verkeerd interpreteren:

# Actual code
echo 'hello' &> /dev/null
echo 'hello' &> /dev/null 'goodbye'

# Desired behavior
echo 'hello' > /dev/null 2>&1
echo 'hello' 'goodbye' > /dev/null 2>&1

# Actual behavior
echo 'hello' &
echo 'hello' & goodbye > /dev/null

OPMERKING: het is bekend dat &> naar wens werkt in zowel Bash als Zsh.

STDERR omleiden

2 is STDERR .

$ echo_to_stderr 2>/dev/null # echos nothing

Definities:

echo_to_stderr is een opdracht die "stderr" naar STDERR

echo_to_stderr () {
    echo stderr >&2
}

$ echo_to_stderr
stderr

Toevoegen versus Trunceren

Afkappen >

  1. Maak een gespecificeerd bestand als het niet bestaat.
  2. Afkappen (inhoud van bestand verwijderen)
  3. Schrijf naar bestand
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines

$ cat /tmp/lines
second line

Toevoegen >>

  1. Maak een gespecificeerd bestand als het niet bestaat.
  2. Bestand toevoegen (schrijven aan het einde van het bestand).
# Overwrite existing file
$ echo "first line" > /tmp/lines

# Append a second line
$ echo "second line" >> /tmp/lines

$ cat /tmp/lines
first line
second line

STDIN, STDOUT en STDERR uitgelegd

Commando's hebben één ingang (STDIN) en twee soorten uitgangen, standaarduitgang (STDOUT) en standaardfout (STDERR).

Bijvoorbeeld:

STDIN

root@server~# read
Type some text here

Standaardinvoer wordt gebruikt om invoer voor een programma te leveren. (Hier zijn we met behulp van de read ingebouwde om een regel uit STDIN te lezen.)

STDOUT

root@server~# ls file
file

Standaarduitvoer wordt meestal gebruikt voor "normale" uitvoer van een opdracht. Bijvoorbeeld, ls geeft bestanden weer, zodat de bestanden naar STDOUT worden verzonden.

STDERR

root@server~# ls anotherfile
ls: cannot access 'anotherfile': No such file or directory

Standaardfout wordt (zoals de naam al aangeeft) gebruikt voor foutmeldingen. Omdat dit bericht geen lijst met bestanden is, wordt het naar STDERR verzonden.

STDIN, STDOUT en STDERR zijn de drie standaard streams. Ze worden aan de schaal geïdentificeerd door een nummer in plaats van een naam:

0 = standaard in
1 = standaard uit
2 = standaardfout

Standaard is STDIN aan het toetsenbord bevestigd en verschijnen zowel STDOUT als STDERR in de terminal. We kunnen STDOUT of STDERR echter omleiden naar wat we nodig hebben. Laten we bijvoorbeeld zeggen dat u alleen de standaarduitgang nodig hebt en dat alle foutmeldingen die op standaardfouten zijn afgedrukt, moeten worden onderdrukt. Dat is wanneer we de descriptoren 1 en 2 .

STDERR omleiden naar / dev / null
In het vorige voorbeeld

root@server~# ls anotherfile 2>/dev/null
root@server~#

In dit geval, als er een STDERR is, wordt deze omgeleid naar / dev / null (een speciaal bestand waarin alles wat erin wordt geplaatst wordt genegeerd), zodat u geen foutuitvoer op de shell krijgt.

Meerdere opdrachten omleiden naar hetzelfde bestand

{
  echo "contents of home directory"
  ls ~
} > output.txt

Benoemde pijpen gebruiken

Soms wilt u misschien iets door het ene programma uitvoeren en in een ander programma invoeren, maar u kunt geen standaardpijp gebruiken.

ls -l | grep ".log"

U kunt eenvoudig naar een tijdelijk bestand schrijven:

touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt

Dit werkt prima voor de meeste toepassingen, maar niemand weet wat tempFile doet en iemand zou het kunnen verwijderen als het de uitvoer van ls -l in die map bevat. Dit is waar een genoemde pijp in het spel komt:

mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe

myPipe is technisch gezien een bestand (alles is in Linux), dus laten we ls -l in een lege map waarin we zojuist een pipe hebben gemaakt in:

mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l

De output is:

prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe

Let op het eerste teken in de machtigingen, het wordt weergegeven als een pijp, niet als een bestand.

Laten we nu iets cools doen.

Open een terminal en noteer de map (of maak er een zodat opruimen gemakkelijk is) en maak een pijp.

mkfifo myPipe

Laten we nu iets in de pijp stoppen.

echo "Hello from the other side" > myPipe

Je zult merken dat dit hangt, de andere kant van de pijp is nog steeds gesloten. Laten we de andere kant van de pijp openen en dat spul doorlaten.

Open een andere terminal en ga naar de map waarin de pijp zich bevindt (of als u deze weet, plaats deze dan voor de pijp):

cat < myPipe

Je zult merken dat nadat hello from the other side is uitgevoerd, het programma in de eerste terminal eindigt, net als dat in de tweede terminal.

Voer de opdrachten nu in omgekeerde volgorde uit. Begin met cat < myPipe en echo er vervolgens iets in. Het werkt nog steeds, omdat een programma wacht totdat er iets in de pijp wordt gestopt voordat het wordt beëindigd, omdat het weet dat het iets moet krijgen.

Benoemde pijpen kunnen nuttig zijn voor het verplaatsen van informatie tussen terminals of tussen programma's.

Buizen zijn klein. Eenmaal vol, blokkeert de schrijver totdat een lezer de inhoud leest, dus u moet de lezer en de schrijver op verschillende terminals uitvoeren of de ene of de andere op de achtergrond uitvoeren:

 ls -l /tmp > myPipe &
 cat < myPipe

Meer voorbeelden met benoemde pijpen:

  • Voorbeeld 1 - alle opdrachten op dezelfde terminal / dezelfde shell

    $ { ls -l && cat file3; } >mypipe &
    $ cat <mypipe    
    # Output: Prints ls -l data and then prints file3 contents on screen
    
  • Voorbeeld 2 - alle opdrachten op dezelfde terminal / dezelfde shell

    $ ls -l >mypipe &
    $ cat file3 >mypipe &
    $ cat <mypipe
    #Output: This prints on screen the contents of mypipe. 
    

    file3 er rekening mee dat de eerste inhoud van file3 wordt weergegeven en vervolgens de ls -l gegevens worden weergegeven (LIFO-configuratie).

  • Voorbeeld 3 - alle opdrachten op dezelfde terminal / dezelfde shell

    $ { pipedata=$(<mypipe) && echo "$pipedata"; } &
    $ ls >mypipe 
    # Output: Prints the output of ls directly on screen 
    

    $pipedata dat de variabele $pipedata niet beschikbaar is voor gebruik in de hoofdterminal / hoofdshell, omdat het gebruik van & een subshell oproept en $pipedata alleen beschikbaar was in deze subshell.

  • Voorbeeld 4 - alle opdrachten op dezelfde terminal / dezelfde shell

    $ export pipedata
    $ pipedata=$(<mypipe) &
    $ ls -l *.sh >mypipe
    $ echo "$pipedata"   
    #Output : Prints correctly the contents of mypipe
    

    Hierdoor wordt de waarde van $pipedata variabele in de hoofdschil correct afgedrukt vanwege de exportaangifte van de variabele. De hoofdterminal / hoofdshell hangt niet vanwege de aanroep van een achtergrondshell ( & ).

Foutmeldingen afdrukken naar stderr

Foutmeldingen worden meestal in een script opgenomen voor foutopsporingsdoeleinden of voor een rijke gebruikerservaring. Schrijf eenvoudig een foutmelding zoals deze:

cmd || echo 'cmd failed'

werkt misschien voor eenvoudige gevallen, maar het is niet de gebruikelijke manier. In dit voorbeeld vervuilt het foutbericht de daadwerkelijke uitvoer van het script door zowel fouten als geslaagde uitvoer in stdout mengen.

Kortom, foutmelding moet naar stderr gaan en niet naar stdout . Het is vrij simpel:

cmd || echo 'cmd failed' >/dev/stderr

Een ander voorbeeld:

if cmd; then
    echo 'success'
else
    echo 'cmd failed' >/dev/stderr
fi

In het bovenstaande voorbeeld wordt het stdout afgedrukt op stdout terwijl het foutbericht wordt afgedrukt op stderr .

Een betere manier om een foutbericht af te drukken, is door een functie te definiëren:

err(){
    echo "E: $*" >>/dev/stderr
}

Wanneer u nu een fout moet afdrukken:

err "My error message"

Omleiding naar netwerkadressen

2.04

Bash behandelt sommige paden als speciaal en kan wat netwerkcommunicatie doen door te schrijven naar /dev/{udp|tcp}/host/port . Bash kan geen luisterserver instellen, maar kan een verbinding tot stand brengen en voor TCP kan de resultaten op zijn minst worden gelezen.

Als u bijvoorbeeld een eenvoudig webverzoek wilt verzenden, kunt u het volgende doen:

exec 3</dev/tcp/www.google.com/80
printf 'GET / HTTP/1.0\r\n\r\n' >&3
cat <&3

en de resultaten van de standaardwebpagina van www.google.com worden afgedrukt naar stdout .

evenzo

printf 'HI\n' >/dev/udp/192.168.1.1/6666

zou een UDP-bericht met HI\n naar een luisteraar sturen op 192.168.1.1:6666



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow