bash: set -x log ke file

18

Saya memiliki skrip shell set -xuntuk memiliki keluaran verbose / debug:

#!/bin/bash

set -x
command1
command2
...

Outputnya terlihat seperti ini:

+ command1
whatever output from command1
+ command2
whatever output from command2

Masalah saya adalah, output shell (disebabkan oleh set -x) pergi ke stderr, dicampur dengan output dari perintah ( command1, command2, ...). Saya akan senang memiliki output "normal" di layar (seperti skrip dijalankan tanpa set -x) dan output "ekstra" dari bash secara terpisah dalam file.

Jadi saya ingin memiliki ini di layar:

whatever output from command1
whatever output from command2

dan ini dalam file log:

+ command1
+ command2

(juga baik jika file log memiliki semuanya)

The set -x 2> filejelas Doens't mengambil efek yang tepat, karena itu bukan output dari perintah set, tapi mengubah perilaku bash.

Menggunakan bash 2> fileuntuk seluruh skrip juga tidak melakukan hal yang benar, karena itu mengarahkan ulang stderr dari setiap perintah yang berjalan di shell ini juga, jadi saya tidak melihat pesan kesalahan dari perintah.

redseven
sumber
2
Google-fu saya tampaknya kuat pagi ini: Kirim bash -x output ke logfile tanpa
menginterupsi

Jawaban:

20

Berdasarkan jawaban ServerFault ini. Kirim bash -x output ke logfile tanpa menginterupsi output standar , versi bash modern menyertakan secara BASH_XTRACEFDspesifik untuk menentukan deskriptor file alternatif untuk output dariset -x

Jadi misalnya bisa Anda lakukan

#!/bin/bash

exec 19>logfile
BASH_XTRACEFD=19

set -x
command1
command2
...

untuk mengirim output set -xke file logfilesambil mempertahankan output standar reguler dan stream kesalahan standar untuk perintah berikut.

Perhatikan bahwa penggunaan fd 19 adalah arbitrer - hanya perlu deskriptor yang tersedia (yaitu bukan 0, 1, 2 atau nomor lain yang telah Anda alokasikan).

Steeldriver
sumber
Memang menyimpan bash trace log secara terpisah, namun sangat sulit untuk membaca 2 output (stdout + stderr pada layar dan bash trace dalam file log) karena mereka benar-benar tidak sinkron. Lihat solusi apa yang baru saja saya posting .
redseven
4

Setelah lebih dari setahun saya telah menemukan solusi yang tepat untuk memiliki keluaran "normal" (stdout + stderr - jejak bash) di layar dan semuanya bersama-sama (stdout + stderr + jejak bash) dalam sebuah file (bash.log) :

exec   > >(tee -ia bash.log)
exec  2> >(tee -ia bash.log >& 2)
exec 19> bash.log

export BASH_XTRACEFD="19"
set -x

command1
command2
redseven
sumber
Itu hanya kombinasi jawaban steeldriver dan yang ini .
jarno
3

Steeldriver memberimu satu pendekatan. Atau, Anda dapat mengarahkan STDERR ke file:

script.sh 2> logfile

Namun, itu berarti bahwa output yang dibuat oleh set -xopsi dan pesan kesalahan lainnya yang dihasilkan akan masuk ke file. Solusi Steeldriver hanya akan mengarahkan ulang set -xoutput yang mungkin Anda inginkan.

terdon
sumber
"... baik output yang dibuat oleh opsi set -x dan pesan kesalahan lainnya yang dihasilkan akan masuk ke file." Dan itulah mengapa itu tidak bekerja untuk saya. Masalah utama saya adalah, saya tidak mudah melihat "kesalahan nyata", karena semua output bash ini masuk ke stderr. Mengarahkan pesan kesalahan perintah juga akan menyembunyikan saya "kesalahan nyata" dengan cara yang berbeda.
redseven
@redseven Saya khawatir apa yang Anda minta tidak begitu jelas. Bisakah Anda mengedit pertanyaan Anda dan menjelaskannya? Coba hindari penggunaan istilah "output" untuk apa pun yang tidak akan stdout. Apakah Anda ingin memisahkan i) output normal; ii) ada kesalahan yang dilemparkan oleh perintah Anda dan iii) set -x? Bukankah jawaban steeldriver cukup? Jika tidak, perlihatkan kepada kami skrip sederhana yang dapat kami salin dan beri tahu kami bagaimana Anda ingin berperilaku.
terdon
@steeldriver sudah menjawab pertanyaan dengan sempurna.
redseven
@redseven ah, keren kalau begitu. Karena komentar Anda datang begitu lama, saya pikir Anda masih membutuhkan sesuatu dan saya tidak bisa melihat bagaimana jawaban steeldriver gagal menyelesaikan masalah Anda. Senang semua sudah beres.
terdon