Arahkan ulang stderr dan stdout di Bash

679

Saya ingin mengarahkan stdout dan stderr dari suatu proses ke satu file. Bagaimana saya melakukannya di Bash?

flybywire
sumber
2
Saya ingin mengatakan ini adalah pertanyaan yang sangat berguna. Banyak orang tidak tahu bagaimana melakukan ini, karena mereka tidak harus sering melakukannya, dan itu bukan perilaku terbaik Bash yang didokumentasikan.
Robert Wm Ruedisueli
2
Terkadang berguna untuk melihat output (seperti biasa) DAN untuk mengarahkannya ke file. Lihat jawabannya oleh Marko di bawah ini. (Saya mengatakan ini di sini karena mudah untuk hanya melihat jawaban yang diterima pertama jika itu cukup untuk menyelesaikan masalah, tetapi jawaban lain sering memberikan informasi yang bermanfaat.)
jvriesem

Jawaban:

763

Coba lihat di sini . Seharusnya:

yourcommand &>filename

(mengalihkan keduanya stdoutdan stderrke nama file).

secara langsung
sumber
29
Sintaks ini tidak digunakan lagi menurut Bash Hackers Wiki . Apakah itu?
Salman von Abbas
20
Menurut wiki.bash-hackers.org/scripting/obsolete , tampaknya sudah usang dalam arti bahwa itu bukan bagian dari POSIX, tetapi halaman bash man tidak menyebutkan itu dihapus dari bash dalam waktu dekat. Halaman manual tidak menentukan preferensi untuk '&>' di atas '> &', yang sebaliknya setara.
chepner
13
Saya kira kita tidak boleh menggunakan &> karena tidak ada dalam POSIX, dan shell umum seperti "dash" tidak mendukungnya.
Sam Watkins
27
Petunjuk tambahan: Jika Anda menggunakan ini dalam skrip, pastikan itu dimulai dengan #!/bin/bashalih - alih #!/bin/sh, karena di membutuhkan bash.
Tor Klingberg
8
Atau & >> untuk menambahkan alih-alih menimpa.
Alexander Gonchiy
449
do_something 2>&1 | tee -a some_file

Ini akan mengarahkan stderr ke stdout dan stdout ke some_file dan mencetaknya ke stdout.

Marko
sumber
16
Pada AIX (ksh) solusi Anda berfungsi. Jawaban yang diterima do_something &>filenametidak. +1.
Dirahasiakan
11
@Aniel, tetapi pertanyaan ini khusus tentang bash
John La Rooy
3
Saya mengerti Ambiguous output redirect.mengapa?
Alexandre Holden Daly
1
Saya memiliki skrip ruby ​​(yang tidak ingin saya modifikasi dengan cara apa pun) yang mencetak pesan kesalahan dengan huruf tebal merah. Script ruby ​​ini kemudian dipanggil dari skrip bash saya (yang dapat saya modifikasi). Ketika saya menggunakan di atas, itu mencetak pesan kesalahan dalam teks biasa, minus pemformatan. Apakah ada cara untuk mempertahankan format di layar dan mendapatkan output (baik stdout dan stderr) dalam file juga?
atlantis
8
Perhatikan bahwa (secara default) ini memiliki efek samping yang $?tidak lagi merujuk pada status keluar do_something, tetapi status keluar tee.
Flimm
255

Anda dapat mengarahkan stderr ke stdout dan stdout ke file:

some_command >file.log 2>&1 

Lihat http://tldp.org/LDP/abs/html/io-redirection.html

Format ini lebih disukai daripada format paling populer yang hanya berfungsi di bash. Dalam Bourne shell itu bisa diartikan sebagai menjalankan perintah di latar belakang. Formatnya juga lebih mudah dibaca 2 (adalah STDERR) dialihkan ke 1 (STDOUT).

EDIT: mengubah urutan seperti yang ditunjukkan dalam komentar

f3lix
sumber
47
Ini mengarahkan ulang stderr ke stdout asli, bukan ke file tempat stdout pergi. Masukkan '2> & 1' setelah '> file.log' dan berfungsi.
1
Apa keuntungan dari pendekatan ini dibandingkan some_command &> file.log?
ubermonkey
6
Jika Anda ingin menambahkan file maka Anda harus melakukannya dengan cara ini: echo "foo" 2> & 1 1 >> bar.txt AFAIK tidak ada cara untuk menambahkan menggunakan &>
SlappyTheFish
9
Argh, maaf, gema "foo" 1 >> bar.txt 2> & 1
SlappyTheFish
11
Saya pikir interpretasi bahwa 2> & 1 mengarahkan stderr ke stdout adalah salah; Saya percaya lebih tepat mengatakan mengirim stderr ke tempat yang sama dengan stdout saat ini. Jadi tempat 2> & 1 setelah pengalihan pertama sangat penting.
jdg
201
# Close STDOUT file descriptor
exec 1<&-
# Close STDERR FD
exec 2<&-

# Open STDOUT as $LOG_FILE file for read and write.
exec 1<>$LOG_FILE

# Redirect STDERR to STDOUT
exec 2>&1

echo "This line will appear in $LOG_FILE, not 'on screen'"

Sekarang, gema sederhana akan menulis ke $ LOG_FILE. Berguna untuk daemonisasi.

Kepada penulis posting asli,

Itu tergantung apa yang perlu Anda capai. Jika Anda hanya perlu mengarahkan kembali / keluar dari perintah yang Anda panggil dari skrip Anda, jawabannya sudah diberikan. Milik saya adalah tentang mengarahkan ulang dalam skrip saat ini yang memengaruhi semua perintah / bawaan (termasuk garpu) setelah cuplikan kode yang disebutkan.


Solusi keren lainnya adalah tentang mengarahkan ulang ke std-err / out AND ke logger atau log file sekaligus yang melibatkan pemisahan "aliran" menjadi dua. Fungsionalitas ini disediakan oleh perintah 'tee' yang dapat menulis / menambahkan ke beberapa file deskriptor (file, soket, pipa, dll) sekaligus: tee FILE1 FILE2 ...> (cmd1)> (cmd2) ...

exec 3>&1 4>&2 1> >(tee >(logger -i -t 'my_script_tag') >&3) 2> >(tee >(logger -i -t 'my_script_tag') >&4)
trap 'cleanup' INT QUIT TERM EXIT


get_pids_of_ppid() {
    local ppid="$1"

    RETVAL=''
    local pids=`ps x -o pid,ppid | awk "\\$2 == \\"$ppid\\" { print \\$1 }"`
    RETVAL="$pids"
}


# Needed to kill processes running in background
cleanup() {
    local current_pid element
    local pids=( "$$" )

    running_pids=("${pids[@]}")

    while :; do
        current_pid="${running_pids[0]}"
        [ -z "$current_pid" ] && break

        running_pids=("${running_pids[@]:1}")
        get_pids_of_ppid $current_pid
        local new_pids="$RETVAL"
        [ -z "$new_pids" ] && continue

        for element in $new_pids; do
            running_pids+=("$element")
            pids=("$element" "${pids[@]}")
        done
    done

    kill ${pids[@]} 2>/dev/null
}

Jadi, sejak awal. Mari kita asumsikan kita memiliki terminal yang terhubung ke / dev / stdout (FD # 1) dan / dev / stderr (FD # 2). Dalam praktiknya, bisa berupa pipa, soket atau apa pun.

  • Buat FD # 3 dan # 4 dan arahkan ke "lokasi" yang sama seperti # 1 dan # 2 masing-masing. Mengubah FD # 1 tidak memengaruhi FD # 3 mulai sekarang. Sekarang, FDs # 3 dan # 4 masing-masing menunjuk ke STDOUT dan STDERR. Ini akan digunakan sebagai terminal nyata STDOUT dan STDERR.
  • 1>> (...) mengalihkan STDOUT ke perintah di parens
  • parens (sub-shell) mengeksekusi pembacaan 'tee' dari STDOUT (pipe) dan mengarahkan ke perintah 'logger' melalui pipa lain ke sub-shell dalam parens. Pada saat yang sama ia menyalin input yang sama ke FD # 3 (terminal)
  • bagian kedua, sangat mirip, adalah tentang melakukan trik yang sama untuk STDERR dan FD # 2 dan # 4.

Hasil menjalankan skrip yang memiliki baris di atas dan tambahan yang ini:

echo "Will end up in STDOUT(terminal) and /var/log/messages"

...adalah sebagai berikut:

$ ./my_script
Will end up in STDOUT(terminal) and /var/log/messages

$ tail -n1 /var/log/messages
Sep 23 15:54:03 wks056 my_script_tag[11644]: Will end up in STDOUT(terminal) and /var/log/messages

Jika Anda ingin melihat gambar yang lebih jelas, tambahkan 2 baris ini ke skrip:

ls -l /proc/self/fd/
ps xf
quizac
sumber
1
hanya satu pengecualian. dalam contoh pertama yang Anda tulis: exec 1 <> $ LOG_FILE. itu menyebabkan file log asli selalu ditulis. untuk loggin nyata cara yang lebih baik adalah: exec 1 >> $ LOG_FILE karena log selalu ditambahkan.
Znik
4
Itu benar meskipun itu tergantung pada niat. Pendekatan saya adalah selalu membuat file log yang unik dan cap waktu. Yang lainnya adalah menambahkan. Kedua cara itu 'dapat dideteksi'. Saya lebih suka file terpisah yang membutuhkan sedikit penguraian tetapi seperti yang saya katakan, apa pun yang membuat perahu Anda mengambang :)
quizac
1
Solusi kedua Anda informatif, tetapi ada apa dengan semua kode pembersihan? Tampaknya tidak relevan, dan jika demikian, hanya mengacaukan contoh yang baik. Saya juga ingin melihatnya dikerjakan ulang sedikit sehingga FD 1 dan 2 tidak dialihkan ke logger melainkan 3 dan 4 sehingga segala sesuatu yang memanggil skrip ini dapat memanipulasi 1 dan 2 lebih jauh dengan asumsi umum stdout == 1 dan stderr == 2, tetapi eksperimen singkat saya menyarankan itu lebih kompleks.
JFlo
1
Saya lebih suka dengan kode pembersihan. Ini mungkin sedikit gangguan dari contoh inti, tetapi pengupasan itu akan membuat contoh tidak lengkap. Net sudah penuh dengan contoh tanpa penanganan kesalahan, atau setidaknya catatan ramah yang masih membutuhkan sekitar seratus baris kode untuk membuatnya aman untuk digunakan.
Zoltan K.
1
Saya ingin menguraikan kode pembersihan. Ini adalah bagian dari skrip yang mengubah ergo menjadi kebal terhadap sinyal HANG-UP. 'tee' dan 'logger' adalah proses yang dihasilkan oleh PPID yang sama dan mereka mewarisi perangkap HUP dari skrip bash utama. Jadi, begitu proses utama mati mereka menjadi diwarisi oleh init [1]. Mereka tidak akan menjadi zombie (mati). Kode pembersihan memastikan bahwa semua tugas latar belakang dimatikan, jika skrip utama mati. Ini juga berlaku untuk proses lain yang mungkin telah dibuat dan berjalan di latar belakang.
quizac
41
bash your_script.sh 1>file.log 2>&1

1>file.logmenginstruksikan shell untuk mengirim STDOUT ke file file.log, dan 2>&1menyuruhnya untuk mengarahkan STDERR (deskriptor file 2) ke STDOUT (deskriptor file 1).

Catatan: Urutan penting seperti yang ditunjukkan oleh liw.fi, 2>&1 1>file.logtidak berfungsi.

Guðmundur H
sumber
21

Anehnya, ini bekerja:

yourcommand &> filename

Tetapi ini memberikan kesalahan sintaksis:

yourcommand &>> filename
syntax error near unexpected token `>'

Anda harus menggunakan:

yourcommand 1>> filename 2>&1

sumber
10
&>>tampaknya bekerja pada BASH 4:$ echo $BASH_VERSION 4.1.5(1)-release $ (echo to stdout; echo to stderr > /dev/stderr) &>> /dev/null
user272735
15

Jawaban singkat: Command >filename 2>&1atauCommand &>filename


Penjelasan:

Pertimbangkan kode berikut yang mencetak kata "stdout" menjadi stdout dan kata "stderror" menjadi stderror.

$ (echo "stdout"; echo "stderror" >&2)
stdout
stderror

Perhatikan bahwa operator '&' memberi tahu bash bahwa 2 adalah deskriptor file (yang mengarah ke stderr) dan bukan nama file. Jika kita meninggalkan tanda '&', perintah ini akan mencetak stdoutke stdout, dan membuat file bernama "2" dan menulis di stderrorsana.

Dengan bereksperimen dengan kode di atas, Anda dapat melihat sendiri bagaimana tepatnya pengalihan operator. Sebagai contoh, dengan mengubah file mana dari dua deskriptor 1,2, diarahkan ke /dev/nulldua baris kode berikut, menghapus semuanya dari stdout, dan semuanya dari stderror masing-masing (mencetak apa yang tersisa).

$ (echo "stdout"; echo "stderror" >&2) 1>/dev/null
stderror
$ (echo "stdout"; echo "stderror" >&2) 2>/dev/null
stdout

Sekarang, kita dapat menjelaskan mengapa solusi mengapa kode berikut tidak menghasilkan keluaran:

(echo "stdout"; echo "stderror" >&2) >/dev/null 2>&1

Untuk benar-benar memahami ini, saya sangat menyarankan Anda membaca halaman web ini pada tabel deskriptor file . Dengan asumsi Anda telah melakukan pembacaan itu, kami dapat melanjutkan. Perhatikan bahwa proses Bash dari kiri ke kanan; dengan demikian Bash melihat >/dev/nullterlebih dahulu (yang sama dengan 1>/dev/null), dan menetapkan file deskriptor 1 untuk menunjuk ke / dev / null bukan stdout. Setelah melakukan ini, Bash kemudian bergerak ke kanan dan melihat 2>&1. Ini mengatur file deskriptor 2 untuk menunjuk ke file yang sama dengan file deskriptor 1 (dan bukan ke file deskriptor 1 sendiri !!!!) (lihat sumber daya ini pada pointeruntuk info lebih lanjut)). Karena file deskriptor 1 menunjuk ke / dev / null, dan file deskriptor 2 menunjuk ke file yang sama dengan file deskriptor 1, file deskriptor 2 sekarang juga menunjuk ke / dev / null. Dengan demikian kedua deskriptor file menunjuk ke / dev / null, dan inilah sebabnya tidak ada output yang diberikan.


Untuk menguji apakah Anda benar-benar memahami konsep tersebut, coba tebak hasilnya ketika kami mengganti urutan pengalihan:

(echo "stdout"; echo "stderror" >&2)  2>&1 >/dev/null

stderror

Alasannya di sini adalah bahwa mengevaluasi dari kiri ke kanan, Bash melihat 2> & 1, dan dengan demikian mengatur file deskriptor 2 untuk menunjuk ke tempat yang sama dengan file deskriptor 1, yaitu stdout. Kemudian set file deskriptor 1 (ingat bahwa> / dev / null = 1> / dev / null) untuk menunjuk ke> / dev / null, sehingga menghapus semua yang biasanya akan dikirim ke standar keluar. Jadi yang tersisa adalah apa yang tidak dikirim ke stdout di subshell (kode dalam tanda kurung) - yaitu "stderror". Hal yang menarik untuk dicatat di sana adalah bahwa meskipun 1 hanya pointer ke stdout, mengarahkan pointer 2 ke 1 via 2>&1TIDAK membentuk rantai pointer 2 -> 1 -> stdout. Jika ya, sebagai akibat dari mengarahkan 1 ke / dev / null, kode2>&1 >/dev/null akan memberikan rantai penunjuk 2 -> 1 -> / dev / null, dan dengan demikian kode tidak akan menghasilkan apa-apa, berbeda dengan yang kita lihat di atas.


Akhirnya, saya perhatikan bahwa ada cara yang lebih sederhana untuk melakukan ini:

Dari bagian 3.6.4 di sini , kita melihat bahwa kita dapat menggunakan operator &>untuk mengarahkan ulang stdout dan stderr. Dengan demikian, untuk mengarahkan kembali output stderr dan stdout dari perintah apa pun ke \dev\null(yang menghapus output), kita cukup mengetik $ command &> /dev/null atau dalam kasus contoh saya:

$ (echo "stdout"; echo "stderror" >&2) &>/dev/null

Takeaways kunci:

  • Deskriptor file berperilaku seperti pointer (meskipun file deskriptor tidak sama dengan pointer file)
  • Mengarahkan deskriptor file "a" ke deskriptor file "b" yang menunjuk ke file "f", menyebabkan deskriptor file "a" untuk menunjuk ke tempat yang sama dengan deskriptor file b - file "f". Ini TIDAK membentuk rantai pointer a -> b -> f
  • Karena hal di atas, ketertiban penting, 2>&1 >/dev/nulladalah! = >/dev/null 2>&1. Satu menghasilkan output dan yang lainnya tidak!

Akhirnya, lihat sumber daya hebat ini:

Dokumentasi Bash tentang Pengalihan , Penjelasan Tabel File Descriptor , Pengantar Pointer

Evan Rosica
sumber
Deskriptor file (0, 1, 2) hanyalah offset ke dalam tabel. Ketika 2> & 1 digunakan efeknya adalah slot FD [2] = dup (1) sehingga dimanapun FD [1] menunjuk FD [2] sekarang menunjuk ke. Ketika Anda mengubah FD [1] ke titik / dev / null, maka FD [1] diubah tetapi tidak mengubah slot FD [2] (yang menunjuk ke stdout). Saya menggunakan istilah dup () karena itu adalah panggilan sistem yang digunakan untuk menduplikasi file descriptor.
PatS
11
LOG_FACILITY="local7.notice"
LOG_TOPIC="my-prog-name"
LOG_TOPIC_OUT="$LOG_TOPIC-out[$$]"
LOG_TOPIC_ERR="$LOG_TOPIC-err[$$]"

exec 3>&1 > >(tee -a /dev/fd/3 | logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_OUT" )
exec 2> >(logger -p "$LOG_FACILITY" -t "$LOG_TOPIC_ERR" )

Ini terkait: Menulis stdOut & stderr ke syslog.

Hampir berhasil, tetapi bukan dari xinted; (


sumber
Saya kira itu tidak berhasil karena "/ dev / fd / 3 Izin ditolak". Mengubah ke> & 3 dapat membantu.
quizac
6

Saya ingin solusi agar keluaran dari stdout plus stderr ditulis ke dalam file log dan stderr masih di konsol. Jadi saya perlu menduplikasi output stderr melalui tee.

Ini adalah solusi yang saya temukan:

command 3>&1 1>&2 2>&3 1>>logfile | tee -a logfile
  • Tukar dulu stderr dan stdout
  • kemudian tambahkan stdout ke file log
  • pipa stderr ke tee dan menambahkannya juga ke file log
bebbo
sumber
BTW, ini tidak berhasil untuk saya (logfile kosong). | tee tidak berpengaruh. Alih-alih, saya membuatnya bekerja menggunakan stackoverflow.com/questions/692000/…
Yaroslav Bulatov
4

Untuk situasi, ketika "perpipaan" diperlukan, Anda dapat menggunakan:

| &

Sebagai contoh:

echo -ne "15\n100\n"|sort -c |& tee >sort_result.txt

atau

TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods |grep node >>js.log  ; done |& sort -h

Solusi berbasis bash ini dapat menyalurkan STDOUT dan STDERR secara terpisah (dari STDERR dari "sort -c" atau dari STDERR ke "sort -h").

dmitry_podyachev
sumber
1

"Termudah" cara (bash4 saja): ls * 2>&- 1>&-.

reim
sumber
1

Fungsi-fungsi berikut dapat digunakan untuk mengotomatiskan proses toggling output antara stdout / stderr dan file log.

#!/bin/bash

    #set -x

    # global vars
    OUTPUTS_REDIRECTED="false"
    LOGFILE=/dev/stdout

    # "private" function used by redirect_outputs_to_logfile()
    function save_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
            exit 1;
        fi
        exec 3>&1
        exec 4>&2

        trap restore_standard_outputs EXIT
    }

    # Params: $1 => logfile to write to
    function redirect_outputs_to_logfile {
        if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
            exit 1;
        fi
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"

        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi

        save_standard_outputs

        exec 1>>${LOGFILE%.log}.log
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
    }

    # "private" function used by save_standard_outputs() 
    function restore_standard_outputs {
        if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: Cannot restore standard outputs because they have NOT been redirected"
            exit 1;
        fi
        exec 1>&-   #closes FD 1 (logfile)
        exec 2>&-   #closes FD 2 (logfile)
        exec 2>&4   #restore stderr
        exec 1>&3   #restore stdout

        OUTPUTS_REDIRECTED="false"
    }

Contoh penggunaan di dalam skrip:

echo "this goes to stdout"
redirect_outputs_to_logfile /tmp/one.log
echo "this goes to logfile"
restore_standard_outputs 
echo "this goes to stdout"
Fernando Fabreti
sumber
ketika saya menggunakan fungsi Anda dan mencoba untuk mengembalikan output standar saya mendapatkan echo: tulis kesalahan: nomor file yang buruk pengalihan berfungsi dengan baik ... pemulihan tampaknya tidak
thum schumacher
untuk menjalankan skrip Anda, saya harus mengomentari baris-baris ini dan saya mengubah urutan: #exec 1> & - #close FD 1 (logfile) #exec 2> & - #close FD 2 (logfile); exec 1> & 3 #restore stdout exec 2> & 4 #restore stderr
thum schumacher
Turut sedih. Saya tidak menerima kesalahan saat menjalankan di CentOS 7, bash 4.2.46. Saya telah membubuhi keterangan referensi tempat saya mendapatkan perintah itu. Ini: Ref: logan.tw/posts/2016/02/20/open-and-close-files-in-bash
Fernando Fabreti
Saya menjalankan perintah ini pada AIX yang mungkin mengapa. Saya menambahkan posting untuk perbaikan yang saya buat.
thum schumacher
1

@ fernando-fabreti

Menambah apa yang Anda lakukan, saya sedikit mengubah fungsinya dan menghapus & - closing dan itu berfungsi untuk saya.

    function saveStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        exec 3>&1
        exec 4>&2
        trap restoreStandardOutputs EXIT
      else
          echo "[ERROR]: ${FUNCNAME[0]}: Cannot save standard outputs because they have been redirected before"
          exit 1;
      fi
  }

  # Params: $1 => logfile to write to
  function redirectOutputsToLogfile {
      if [ "$OUTPUTS_REDIRECTED" == "false" ]; then
        LOGFILE=$1
        if [ -z "$LOGFILE" ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: logfile empty [$LOGFILE]"
        fi
        if [ ! -f $LOGFILE ]; then
            touch $LOGFILE
        fi
        if [ ! -f $LOGFILE ]; then
            echo "[ERROR]: ${FUNCNAME[0]}: creating logfile [$LOGFILE]"
            exit 1
        fi
        saveStandardOutputs
        exec 1>>${LOGFILE}
        exec 2>&1
        OUTPUTS_REDIRECTED="true"
      else
        echo "[ERROR]: ${FUNCNAME[0]}: Cannot redirect standard outputs because they have been redirected before"
          exit 1;
      fi
  }
  function restoreStandardOutputs {
      if [ "$OUTPUTS_REDIRECTED" == "true" ]; then
      exec 1>&3   #restore stdout
      exec 2>&4   #restore stderr
      OUTPUTS_REDIRECTED="false"
     fi
  }
  LOGFILE_NAME="tmp/one.log"
  OUTPUTS_REDIRECTED="false"

  echo "this goes to stdout"
  redirectOutputsToLogfile $LOGFILE_NAME
  echo "this goes to logfile"
  echo "${LOGFILE_NAME}"
  restoreStandardOutputs 
  echo "After restore this goes to stdout"
schumacher mereka
sumber
1

Dalam situasi ketika Anda mempertimbangkan untuk menggunakan hal-hal seperti exec 2>&1saya merasa lebih mudah dibaca jika mungkin menulis ulang kode menggunakan fungsi bash seperti ini:

function myfunc(){
  [...]
}

myfunc &>mylog.log
pengguna2761220
sumber
0

Untuk tcsh, saya harus menggunakan perintah berikut:

command >& file

Jika digunakan command &> file, itu akan memberikan kesalahan "Perintah null tidak valid".

einstein6
sumber