Bash
Omdirigering
Sök…
Syntax
- kommando </ path / to / file # Omdirigera standardinmatning till fil
- kommando> / path / to / file # Redirect standard output to flie
- kommandot file_descriptor> / path / to / file # Redirect output of file_descriptor to file
- kommando> & file_descriptor # Redirect output till file_descriptor
- command file_descriptor> & another_file_descriptor # Redirect file_descriptor to another_file_descriptor
- kommando <& file_descriptor # omdirigera file_descriptor till standardinmatning
- kommando &> / sökväg / till / fil # Omdirigera standardutdata och standardfel till fil
parametrar
Parameter | detaljer |
---|---|
intern filbeskrivning | Ett heltal. |
riktning | En av > , < eller <> |
extern filbeskrivning eller sökväg | & följt av ett heltal för filbeskrivning eller en sökväg. |
Anmärkningar
UNIX-konsolprogram har en inmatningsfil och två utgångsfiler (in- och utgångsströmmar, liksom enheter, behandlas som filer av operativsystemet.) Dessa är vanligtvis tangentbordet respektive skärmen, men alla eller alla av dem kan omdirigeras. att komma från - eller gå till - en fil eller annat program.
STDIN
är standardinmatning och är hur programmet får interaktiv inmatning. STDIN
tilldelas vanligtvis filbeskrivning 0.
STDOUT
är standardutgång. Vad som än släpps ut på STDOUT
betraktas som "resultatet" av programmet. STDOUT
tilldelas vanligtvis filbeskrivning 1.
STDERR
är där felmeddelanden visas. Vanligtvis, när man kör ett program från konsolen, STDERR
ut på skärmen och kan inte STDOUT
från STDOUT
. STDERR
tilldelas vanligtvis filbeskrivning 2.
Omdirigeringsordningen är viktig
command > file 2>&1
Omdirigerar både ( STDOUT
och STDERR
) till filen.
command 2>&1 > file
Omdirigerar endast STDOUT
, eftersom filbeskrivaren 2 omdirigeras till den fil som pekas ut med filbeskrivning 1 (vilket inte är file
ännu när uttalandet utvärderas).
Varje kommando i en pipeline har sin egen STDERR
(och STDOUT
) eftersom var och en är en ny process. Detta kan skapa överraskande resultat om du förväntar dig att en omdirigering påverkar hela pipeline. Till exempel detta kommando (inslaget för läsbarhet):
$ python -c 'import sys;print >> sys.stderr, "Python error!"' \
| cut -f1 2>> error.log
kommer att skriva ut "Python-fel!" till konsolen snarare än loggfilen. I stället bifogar felet till kommandot du vill fånga:
$ python -c 'import sys;print >> sys.stderr, "Python error!"' 2>> error.log \
| cut -f1
Omdirigerar standardutgången
>
omdirigera standardutgången (aka STDOUT
) för det aktuella kommandot till en fil eller annan beskrivning.
Dessa exempel skriver utdata från ls
kommandot i filen file.txt
ls >file.txt
> file.txt ls
Målfilen skapas om den inte finns, annars blir den här filen trunkerad.
Standardomdirigeringsbeskrivningen är standardutdata eller 1
när ingen anges. Detta kommando motsvarar de tidigare exemplen med standardutgången uttryckligen angiven:
ls 1>file.txt
Obs: omdirigeringen initieras av det exekverade skalet och inte av det exekverade kommandot, därför görs det före kommandot exekvering.
Omdirigerar STDIN
<
läser från sitt högra argument och skriver till sitt vänstra argument.
För att skriva en fil till STDIN
bör vi läsa /tmp/a_file
och skriva till STDIN
dvs. 0</tmp/a_file
Obs: Intern filbeskrivning är standard 0
( STDIN
) för <
$ echo "b" > /tmp/list.txt
$ echo "a" >> /tmp/list.txt
$ echo "c" >> /tmp/list.txt
$ sort < /tmp/list.txt
a
b
c
Omdirigerar både STDOUT och STDERR
Filbeskrivare som 0
och 1
är pekare. Vi ändrar vad filbeskrivare pekar på med omdirigering. >/dev/null
betyder 1
poäng till /dev/null
.
Först pekar vi 1
( STDOUT
) till /dev/null
sedan punkt 2
( STDERR
) till vad 1
pekar på.
# STDERR is redirect to STDOUT: redirected to /dev/null,
# effectually redirecting both STDERR and STDOUT to /dev/null
echo 'hello' > /dev/null 2>&1
Detta kan förkortas ytterligare till följande:
echo 'hello' &> /dev/null
Denna form kan emellertid vara oönskad vid produktion om skalkompatibilitet är en oro eftersom den är i konflikt med POSIX, introducerar tolkning av tvetydighet och skal utan denna funktion kommer att tolka den felaktigt:
# 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
OBS: &>
är känd för att fungera som önskat i både Bash och Zsh.
Omdirigerar STDERR
2
är STDERR
.
$ echo_to_stderr 2>/dev/null # echos nothing
Definitioner:
echo_to_stderr
är ett kommando som skriver "stderr"
till STDERR
echo_to_stderr () {
echo stderr >&2
}
$ echo_to_stderr
stderr
Lägg till vs Trunkera
Avkorta >
- Skapa angiven fil om den inte finns.
- Avka (ta bort filens innehåll)
- Skriv till fil
$ echo "first line" > /tmp/lines
$ echo "second line" > /tmp/lines
$ cat /tmp/lines
second line
Bifoga >>
- Skapa angiven fil om den inte finns.
- Lägg till fil (skrivning i slutet av filen).
# 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 och STDERR förklarade
Kommandon har en ingång (STDIN) och två typer av utgångar, standardutgång (STDOUT) och standardfel (STDERR).
Till exempel:
STDIN
root@server~# read
Type some text here
Standardinmatning används för att tillhandahålla input till ett program. (Här använder vi den read
inbyggda för att läsa en linje från STDIN.)
STDOUT
root@server~# ls file
file
Standardutgång används vanligtvis för "normal" utgång från ett kommando. Till exempel ls
listar filer, så filerna skickas till STDOUT.
STDERR
root@server~# ls anotherfile
ls: cannot access 'anotherfile': No such file or directory
Standardfel används (som namnet antyder) för felmeddelanden. Eftersom det här meddelandet inte är en lista med filer skickas det till STDERR.
STDIN, STDOUT och STDERR är de tre standardströmmarna. De identifieras i skalet med ett nummer snarare än ett namn:
0 = Standard i
1 = Standard ut
2 = Standardfel
Som standard är STDIN ansluten till tangentbordet och både STDOUT och STDERR visas i terminalen. Vi kan emellertid omdirigera antingen STDOUT eller STDERR till vad vi behöver. Låt oss till exempel säga att du bara behöver standard ut och alla felmeddelanden som skrivs ut på standardfel ska undertrycks. Det är när vi använder beskrivarna 1
och 2
.
Omdirigerar STDERR till / dev / null
Med föregående exempel,
root@server~# ls anotherfile 2>/dev/null
root@server~#
I det här fallet, om det finns någon STDERR, kommer den att omdirigeras till / dev / null (en speciell fil som ignorerar någonting som läggs i den), så att du inte får något fel på skalet.
Omdirigera flera kommandon till samma fil
{
echo "contents of home directory"
ls ~
} > output.txt
Använda namngivna rör
Ibland kanske du vill skriva ut något av ett program och mata in det i ett annat program, men kan inte använda ett standardrör.
ls -l | grep ".log"
Du kan helt enkelt skriva till en tillfällig fil:
touch tempFile.txt
ls -l > tempFile.txt
grep ".log" < tempFile.txt
Detta fungerar bra för de flesta applikationer, men ingen kommer att veta vad tempFile
gör och någon kan ta bort den om den innehåller output från ls -l
i den katalogen. Det är här ett namngivet rör spelar in:
mkfifo myPipe
ls -l > myPipe
grep ".log" < myPipe
myPipe
är tekniskt en fil (allt finns i Linux), så låt oss göra ls -l
i en tom katalog som vi just skapade ett rör i:
mkdir pipeFolder
cd pipeFolder
mkfifo myPipe
ls -l
Utgången är:
prw-r--r-- 1 root root 0 Jul 25 11:20 myPipe
Lägg märke till det första tecknet i behörigheterna, det är listat som ett rör, inte en fil.
Låt oss göra något coolt.
Öppna en terminal och notera katalogen (eller skapa en så att rensningen är enkel) och skapa ett rör.
mkfifo myPipe
Låt oss nu sätta något i röret.
echo "Hello from the other side" > myPipe
Du kommer att märka att detta hänger, den andra sidan av röret är fortfarande stängd. Låt oss öppna upp den andra sidan av röret och låt det gå igenom.
Öppna en annan terminal och gå till katalogen som röret är i (eller om du vet det, beroende på det på röret):
cat < myPipe
Du kommer att märka att efter att hello from the other side
har matats ut slutar programmet i den första terminalen, liksom det i den andra terminalen.
Kör nu kommandona i omvänd riktning. Börja med cat < myPipe
och echo sedan något in i den. Det fungerar fortfarande, eftersom ett program kommer att vänta tills något sätts i röret innan det avslutas, eftersom det vet att det måste få något.
Namngivna rör kan vara användbara för att flytta information mellan terminaler eller mellan program.
Rören är små. När det är fullt blockerar författaren tills någon läsare läser innehållet, så du måste antingen köra läsaren och författaren i olika terminaler eller köra den ena eller den andra i bakgrunden:
ls -l /tmp > myPipe &
cat < myPipe
Fler exempel med namngivna rör:
Exempel 1 - alla kommandon på samma terminal / samma skal
$ { ls -l && cat file3; } >mypipe & $ cat <mypipe # Output: Prints ls -l data and then prints file3 contents on screen
Exempel 2 - alla kommandon på samma terminal / samma skal
$ ls -l >mypipe & $ cat file3 >mypipe & $ cat <mypipe #Output: This prints on screen the contents of mypipe.
Tänk på att först innehållet i
file3
visas och sedan visasls -l
data (LIFO-konfiguration).Exempel 3 - alla kommandon på samma terminal / samma skal
$ { pipedata=$(<mypipe) && echo "$pipedata"; } & $ ls >mypipe # Output: Prints the output of ls directly on screen
Tänk på att variabeln
$pipedata
inte är tillgänglig för användning i huvudterminalen / huvudskalet eftersom användningen av&
åberopar ett underskal och$pipedata
endast var tillgängligt i det här underskalet.Exempel 4 - alla kommandon på samma terminal / samma skal
$ export pipedata $ pipedata=$(<mypipe) & $ ls -l *.sh >mypipe $ echo "$pipedata" #Output : Prints correctly the contents of mypipe
Detta skriver korrekt ut värdet på
$pipedata
variabeln i huvudskalet på grund av exportdeklarationen för variabeln. Huvudterminalen / huvudskalet hänger inte på grund av att ett bakgrundsskal (&
) kallas.
Skriv ut felmeddelanden till stderr
Felmeddelanden ingår generellt i ett skript för felsökning eller för att ge en rik användarupplevelse. Skriv bara felmeddelande så här:
cmd || echo 'cmd failed'
kan fungera för enkla fall men det är inte det vanliga sättet. I det här exemplet kommer felmeddelandet att förorena den verkliga utgången från skriptet genom att blanda både fel och framgångsrik utgång i stdout
.
Kort sagt ska felmeddelandet gå till stderr
not stdout
. Det är ganska enkelt:
cmd || echo 'cmd failed' >/dev/stderr
Ett annat exempel:
if cmd; then
echo 'success'
else
echo 'cmd failed' >/dev/stderr
fi
I exemplet ovan kommer framgångsmeddelandet att skrivas ut på stdout
medan felmeddelandet skrivs ut på stderr
.
Ett bättre sätt att skriva ut felmeddelande är att definiera en funktion:
err(){
echo "E: $*" >>/dev/stderr
}
Nu när du måste skriva ut ett fel:
err "My error message"
Omdirigering till nätverksadresser
Bash behandlar vissa vägar som speciella och kan göra viss nätverkskommunikation genom att skriva till /dev/{udp|tcp}/host/port
. Bash kan inte konfigurera en lyssnande server, men kan initiera en anslutning och för TCP kan läsa resultaten åtminstone.
För att till exempel skicka en enkel webbförfrågan kan man göra:
exec 3</dev/tcp/www.google.com/80
printf 'GET / HTTP/1.0\r\n\r\n' >&3
cat <&3
och resultaten från www.google.com
standardwebbplats skrivs ut till stdout
.
Liknande
printf 'HI\n' >/dev/udp/192.168.1.1/6666
skickade ett UDP-meddelande som innehåller HI\n
till en lyssnare den 192.168.1.1:6666