Saya berasumsi Anda masih ingin melihat STDERR dan STDOUT di terminal. Anda bisa memilih jawaban Josh Kelley, tetapi saya menemukan menyimpan tail
sekitar di latar belakang yang menghasilkan file log Anda sangat retas dan kaku. Perhatikan bagaimana Anda perlu menyimpan exra FD dan melakukan pembersihan sesudahnya dengan mematikannya dan secara teknis harus melakukannya di trap '...' EXIT
.
Ada cara yang lebih baik untuk melakukannya, dan Anda telah menemukannya:tee
.
Hanya saja, alih-alih hanya menggunakannya untuk stdout Anda, miliki tee untuk stdout dan satu untuk stderr. Bagaimana Anda akan mencapai ini? Substitusi proses dan pengalihan file:
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)
Mari kita bagi dan jelaskan:
> >(..)
>(...)
(substitusi proses) membuat FIFO dan memungkinkan tee
mendengarkannya. Kemudian, ia menggunakan >
(pengalihan file) untuk mengalihkan STDOUT dari command
ke FIFO bahwa tee
pertama Anda sedang mendengarkan.
Hal yang sama untuk yang kedua:
2> >(tee -a stderr.log >&2)
Kami menggunakan substitusi proses lagi untuk membuat tee
proses yang membaca dari STDIN dan membuangnya ke stderr.log
. tee
mengeluarkan inputnya kembali pada STDOUT, tetapi karena inputnya adalah STDERR kami, kami ingin mengarahkan ulang tee
STDOUT ke STDERR kami lagi. Kemudian kami menggunakan pengalihan file untuk mengarahkan ulang command
STDERR ke input FIFO (tee
STDIN).
Lihat http://mywiki.wooledge.org/BashGuide/InputAndOutput
Pergantian proses adalah salah satu hal yang sangat menyenangkan yang Anda dapatkan sebagai bonus memilih bash
sebagai shell Anda sebagai lawan dari sh
(POSIX atau Bourne).
Di sh
, Anda harus melakukannya secara manual:
out="${TMPDIR:-/tmp}/out.$$" err="${TMPDIR:-/tmp}/err.$$"
mkfifo "$out" "$err"
trap 'rm "$out" "$err"' EXIT
tee -a stdout.log < "$out" &
tee -a stderr.log < "$err" >&2 &
command >"$out" 2>"$err"
mengapa tidak cukup:
./aaa.sh 2>&1 | tee -a log
Ini hanya mengalihkan stderr
ke stdout
, jadi tee menggemakan log dan screen. Mungkin saya melewatkan sesuatu, karena beberapa solusi lain tampaknya sangat rumit.
Catatan: Sejak bash versi 4 Anda dapat menggunakan |&
sebagai singkatan dari 2>&1 |
:
./aaa.sh |& tee -a log
Ini mungkin berguna bagi orang yang menemukan ini melalui google. Cukup batalkan komentar pada contoh yang ingin Anda coba. Tentu saja, jangan ragu untuk mengganti nama file keluaran.
#!/bin/bash
STATUSFILE=x.out
LOGFILE=x.log
### All output to screen
### Do nothing, this is the default
### All Output to one file, nothing to the screen
#exec > ${LOGFILE} 2>&1
### All output to one file and all output to the screen
#exec > >(tee ${LOGFILE}) 2>&1
### All output to one file, STDOUT to the screen
#exec > >(tee -a ${LOGFILE}) 2> >(tee -a ${LOGFILE} >/dev/null)
### All output to one file, STDERR to the screen
### Note you need both of these lines for this to work
#exec 3>&1
#exec > >(tee -a ${LOGFILE} >/dev/null) 2> >(tee -a ${LOGFILE} >&3)
### STDOUT to STATUSFILE, stderr to LOGFILE, nothing to the screen
#exec > ${STATUSFILE} 2>${LOGFILE}
### STDOUT to STATUSFILE, stderr to LOGFILE and all output to the screen
#exec > >(tee ${STATUSFILE}) 2> >(tee ${LOGFILE} >&2)
### STDOUT to STATUSFILE and screen, STDERR to LOGFILE
#exec > >(tee ${STATUSFILE}) 2>${LOGFILE}
### STDOUT to STATUSFILE, STDERR to LOGFILE and screen
#exec > ${STATUSFILE} 2> >(tee ${LOGFILE} >&2)
echo "This is a test"
ls -l sdgshgswogswghthb_this_file_will_not_exist_so_we_get_output_to_stderr_aronkjegralhfaff
ls -l ${0}