Mens du bruker nohup for å sette en kommando for å kjøre i bakgrunnen, vises noe av innholdet i terminalen.
cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Jeg vil lagre innholdet i en fil.
Det er to hovedutdatastrømmer i Linux (og andre operativsystemer), standardutdata (stdout) og standardfeil (stderr). Feilmeldinger, som de du viser, skrives ut til standardfeil. Den klassiske omdirigeringsoperatoren (command > file
) omdirigerer bare standardutdata, så standardfeil vises fortsatt på terminalen. For å omdirigere stderr også, har du noen få valg:
Omdirigere stdout til en fil og stderr til en annen fil:
kommando > ut 2>feil
Omdiriger stdout til en fil (>out
), og omdiriger deretter stderr til stdout (2>&1
):
kommando >out 2>&1`.
Omdiriger begge til en fil (dette støttes ikke av alle skall, bash
og zsh
støtter det for eksempel, men sh
og ksh
gjør det ikke):
kommando &> ut
For mer informasjon om de ulike kontroll- og omdirigeringsoperatorene, se her.
Den første tingen å merke seg er at det er et par måter avhengig av formålet og skallet ditt, derfor krever dette en liten forståelse av flere aspekter. I tillegg, visse kommandoer som time
og strace
skrive utdata til stderr som standard, og kan eller ikke kan gi en metode for omdirigering som er spesifikk for den kommandoen
Grunnleggende teori bak omdirigering er at en prosess skapt av skallet (forutsatt at det er en ekstern kommando og ikke innebygd i skallet) opprettes via fork()
og execve()
syscalls, og før det skjer, utfører et annet syscall dup2()
nødvendige omdirigeringer før execve()
skjer. I den forstand arves omdirigeringer fra det overordnede skallet. m&>n
og m>n.txt
informerer skallet om hvordan det skal utføre open()
og dup2()
syscall (se også How input redirection works, What is the difference between redirection and pipe, og What does & exactly mean in output redirection )
Mest typisk, er via 2>
i Bourne-lignende skall, for eksempel dash
(som er symlinked til /bin/sh
) og bash
; den første er standard og POSIX-kompatibelt skall og den andre er det de fleste brukere bruker for interaktive økter. De er forskjellige i syntaks og funksjoner, men heldigvis for oss fungerer omdirigering av feilstrøm på samme måte (bortsett fra &>
ikke-standard). I tilfelle av csh og dets derivater, stderr omdirigering fungerer ikke helt der..
La oss komme tilbake til 2>
del. To viktige ting å legge merke til: >
betyr omdirigering operatør, der vi åpner en fil og 2
heltall står for stderr fil descriptor; faktisk er dette nøyaktig hvordan POSIX standard for shell språk definerer omdirigering i avsnitt 2.7:
[n]redir-op word
For enkel >
omdirigering er 1
heltallet underforstått for stdout
, dvs. echo Hello World > /dev/null
er akkurat det samme som echo Hello World 1>/dev/null
. Legg merke til at heltall eller omdirigeringsoperatoren ikke kan siteres, ellers gjenkjenner ikke skallet dem som sådan, og behandler dem i stedet som bokstavelig tekststreng. Når det gjelder mellomrom, er det viktig at heltall er rett ved siden av omdirigeringsoperatoren, men fil kan enten være ved siden av omdirigeringsoperatoren eller ikke, dvs. kommando 2>/dev/null
og kommando 2> /dev/null
vil fungere helt fint.
Den noe forenklede syntaksen for typisk kommando i shell vil være
command [arg1] [arg2] 2> /dev/null
Trikset her er at omdirigering kan vises hvor som helst. Det er både 2> kommando [arg1]
og kommando 2> [arg1]
er gyldige. Merk at for bash
shell, det finnes & >
måte å omdirigere både stdout og stderr-strømmer samtidig, men igjen - det er bash-spesifikt, og hvis du streber etter portabilitet av skript, kan det hende det ikke fungerer. Se også Ubuntu Wiki og Hva er forskjellen mellom &> og 2>&1.
Merk: Omdirigeringsoperatoren >
avkorter en fil og overskriver den, hvis filen finnes. 2>>kan brukes til å legge til
stderrtil filen. Som du kanskje legger merke til, er
>ment for en enkelt kommando. For skript kan vi omdirigere stderr-strømmen til hele skriptet utenfra som i
myscript.sh 2> /dev/null`, eller vi kan bruke exec built-in. Den innebygde exec har kraften til å omkoble strømmen for hele skalløkten, så å si, enten interaktivt eller via skript. Noe sånt som
#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
I dette eksemplet skal loggfilen vise stat: cannot stat '/etc/non_existing_file': Ingen slik fil eller katalog
.
En annen måte er via funksjoner. Som kopciuszek bemerket i sitt svar, kan vi skrive funksjonserklæring med allerede vedlagt omdirigering, det vil si
some_function(){
command1
command2
} 2> my_log_file.txt
Kommandoer som time
og strace
skriver utdata til stderr som standard. Når det gjelder time
-kommandoen, er det eneste levedyktige alternativet å omdirigere utdata for hele kommandoen, dvs.
time echo foo 2>&1 > file.txt
alternativt kan synkron liste eller subshell omdirigeres hvis du vil skille utdataene (som vist i relatert innlegg ):
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
Andre kommandoer, som strace
eller dialog
gir midler til å omdirigere stderr. strace
har -o <filnavn.txt>
alternativ som gjør det mulig å spesifisere filnavn der utdata skal skrives. Det er også et alternativ for å skrive en tekstfil for hver delprosess som strace
ser. Kommandoen dialog
skriver tekstbrukergrensesnittet til stdout, men utdata til stderr, så for å lagre utdata til variabel (fordi var=$(...)
og pipelines bare mottar stderr) må vi bytte filbeskrivelsene
result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
men i tillegg er det --output-fd
flagg, som vi også kan bruke. Det' s også metoden for navngitte rør. Jeg anbefaler å lese det lenkede innlegget om dialog
-kommandoen for grundig beskrivelse av hva som skjer.