Naudojant nohup, kad komanda būtų paleista fone, terminale rodomas tam tikras turinys.
cp: error reading ‘/mnt/tt/file.txt’: Input/output error
cp: failed to extend ‘/mnt/tt/file.txt’: Input/output error
Noriu išsaugoti šį turinį į failą.
"Linux" (ir kitose OS) yra du pagrindiniai išvesties srautai: standartinė išvestis (stdout) ir standartinė klaida (stderr). Klaidų pranešimai, pavyzdžiui, tie, kuriuos rodote, spausdinami į standartinę klaidą. Klasikinis nukreipimo operatorius (komanda > failas
) nukreipia tik standartinę išvestį, todėl standartinė klaida vis tiek rodoma terminale. Norėdami nukreipti ir stderr, turite keletą pasirinkimų:
Peradresuoti stdout į vieną failą, o stderr - į kitą failą:
iš 2>klaida
Peradresuokite stdout į failą (>out
), o tada nukreipkite stderr į stdout (2>&1
):
komanda >out 2>&1
Peradresuokite abu į failą (tai palaiko ne visos kriauklės, pavyzdžiui, bash
ir zsh
palaiko, o sh
ir ksh
- ne):
komanda &> out
Daugiau informacijos apie įvairius valdymo ir nukreipimo operatorius rasite čia.
Pirmiausia reikia atkreipti dėmesį į tai, kad yra keletas būdų, priklausomai nuo jūsų tikslo ir apvalkalo, todėl reikia šiek tiek suprasti kelis aspektus. Be to, tam tikros komandos, pavyzdžiui, time
ir strace
, pagal nutylėjimą išvestį rašo į stderr, ir gali būti arba nebūti konkrečiai tai komandai būdingo nukreipimo būdo
Pagrindinė nukreipimo teorija yra ta, kad procesas, kurį paleidžia apvalkalas (darant prielaidą, kad tai yra išorinė komanda, o ne apvalkale integruota komanda), sukuriamas per fork()
ir execve()
syscall, o prieš tai kitas syscall dup2()
atlieka būtinus nukreipimus prieš execve()
. Šia prasme nukreipimai paveldimi iš pagrindinio apvalkalo. m&>n
ir m>n.txt
informuoja apvalkalą apie tai, kaip atlikti open()
ir dup2()
syscall (taip pat žr. straipsnius Kaip veikia įvesties nukreipimas, Kuo skiriasi nukreipimas ir pipe ir Ką tiksliai reiškia & išvesties nukreipime )
Tipiškiausias peradresavimas yra per 2>
Bourne'o tipo apvalkale, pavyzdžiui, dash
(kuris yra susietas su /bin/sh
) ir bash
; pirmasis yra numatytasis ir POSIX reikalavimus atitinkantis apvalkalas, o antrąjį dauguma naudotojų naudoja interaktyviai sesijai. Jos skiriasi sintakse ir funkcijomis, bet, mūsų laimei, klaidų srauto nukreipimas veikia vienodai (išskyrus &>
nestandartinį). Csh ir jo išvestinių programų atveju stderr nukreipimas ne visai veikia.
Grįžkime prie 2>
dalies. Atkreipkite dėmesį į du svarbiausius dalykus: >
reiškia nukreipimo operatorių, kai atidarome failą, o 2
sveikasis skaičius reiškia stderr failo deskriptorių; iš tikrųjų būtent taip POSIX standartas, skirtas apvalkalo kalbai, apibrėžia nukreipimą 2.7 skirsnyje:
[n]redir-op word
Paprasto >
nukreipimo atveju 1
sveikasis skaičius reiškia stdout
, t. y. echo Hello World > /dev/null
yra tas pats, kas echo Hello World 1>/dev/null
. Atkreipkite dėmesį, kad sveikojo skaičiaus arba nukreipimo operatoriaus negalima pateikti kabutėse, kitaip shell jų neatpažins, o traktuos kaip pažodinę teksto eilutę. Kalbant apie tarpus, svarbu, kad integer būtų prie pat nukreipimo operatoriaus, tačiau failas gali būti prie pat nukreipimo operatoriaus arba ne, t. y. komanda 2>/dev/null
ir komanda 2> /dev/null
veiks puikiai.
Šiek tiek supaprastinta tipinės shell komandos sintaksė būtų tokia
command [arg1] [arg2] 2> /dev/null
Čia gudrybė ta, kad nukreipimas gali atsirasti bet kurioje vietoje. Tai reiškia, kad galioja ir 2> komanda [arg1]
, ir komanda 2> [arg1]
. Atkreipkite dėmesį, kad bash
apvalkale yra &>
būdas vienu metu nukreipti ir stdout, ir stderr srautus, bet vėlgi - jis būdingas tik bash, ir jei siekiate, kad scenarijus būtų perkeliamas, jis gali netikti. Taip pat žr. Ubuntu Wiki ir Koks skirtumas tarp &> ir 2>&1.
Pastaba: Peradresavimo operatorius >
atkerta failą ir jį perrašo, jei failas egzistuoja. Operatorius 2>>
gali būti naudojamas prie failo pridedant stderr
.
Jei pastebėjote, >
skirtas vienai komandai. Skriptams galime nukreipti viso scenarijaus stderr srautą iš išorės, kaip myscript.sh 2> /dev/null
, arba galime pasinaudoti exec built-in. Exec built-in turi galią peradresuoti srautą visai apvalkalo sesijai, taip sakant, tiek interaktyviai, tiek per scenarijų. Kažkas panašaus į
#!/bin/sh
exec 2> ./my_log_file.txt
stat /etc/non_existing_file
Šiame pavyzdyje žurnalo failas turėtų rodyti `stat: cannot stat '/etc/non_existing_file': Tokio failo ar katalogo nėra. Dar vienas būdas - per funkcijas. Kaip savo atsakyme pažymėjo kopciuszek, galime parašyti funkcijos deklaraciją su jau pridėtu nukreipimu, t. y.
some_function(){
command1
command2
} 2> my_log_file.txt
Tokios komandos, kaip time
ir strace
, pagal nutylėjimą savo išvestį rašo į stderr. Komandos time
atveju vienintelė tinkama alternatyva yra nukreipti visos komandos išvestį, t. y.
time echo foo 2>&1 > file.txt
taip pat galima nukreipti sinchroninį sąrašą arba posistemę, jei norite atskirti išvestį ( kaip parodyta susijusiame pranešime ):
{ time sleep 1 2> sleep.stderr ; } 2> time.txt
Kitos komandos, pavyzdžiui, strace
arba dialog
, suteikia priemonių nukreipti stderr. strace
turi -o <filename.txt>
parinktį, kuri leidžia nurodyti failo, į kurį turi būti įrašytas išėjimas, vardą. Taip pat yra parinktis, leidžianti rašyti tekstinį failą kiekvienam paprocesui, kurį mato strace
. Komanda dialog
tekstinę vartotojo sąsają rašo į stdout, o išvestį - į stderr, todėl norėdami išsaugoti jos išvestį kintamajame ( nes var=$(...)
, o pipelines gauna tik stderr ) turime sukeisti failų deskriptorius vietomis
result=$(dialog --inputbox test 0 0 2>&1 1>/dev/tty);
bet papildomai yra --output-fd
vėliava, kurią taip pat galime panaudoti. Taip pat yra įvardytų vamzdžių metodas. Rekomenduoju perskaityti susietą įrašą apie dialog
komandą, kad išsamiai aprašytumėte, kas vyksta.