Kirim bash -x output ke logfile tanpa menginterupsi output standar

12

Apakah ada cara untuk mengirim informasi yang ditampilkan dengan menjalankan skrip bash dengan opsi -x ke file, sementara tidak mengubah output standar yang terlihat oleh pengguna yang menjalankan skrip?

Ini adalah fitur debug yang ingin saya terapkan dalam skrip bash yang sering kami gunakan untuk mengubahnya.

Sangat dihargai.

maaf dokter pink
sumber

Jawaban:

21

Output dari -x menuju ke stderr, bukan stdout. Tetapi bahkan itu bisa menjadi masalah - banyak skrip akan memiliki dependensi fungsional pada konten stderr, dan jenisnya berantakan untuk memiliki debug dan stream stderr dicampur bersama dalam beberapa kasus.

Versi Bash> 4.1 memang menawarkan solusi yang berbeda: variabel lingkungan BASH_XTRACEFD memungkinkan Anda menentukan deskriptor file yang akan digunakan untuk mengirim aliran debug. Ini bisa berupa file atau pipa atau kebaikan unix-y lainnya yang Anda suka.

# Use FD 19 to capture the debug stream caused by "set -x":
exec 19>/tmp/my-script.log
# Tell bash about it  (there's nothing special about 19, its arbitrary)
export BASH_XTRACEFD=19

# turn on the debug stream:
set -x

# run some commands:
cd /etc
find 
echo "Well, that was fun."

# Close the output:
set +x
exec 19>&-

# See what we got:
cat /tmp/my-script.log

Dengan sedikit mengutak-atik, Anda dapat melakukan hal-hal lain - seperti melakukan 'tee' pada stdout dan / atau stdin stream, dan interleave dengan output debug, sehingga log Anda lebih lengkap. Untuk detail lebih lanjut tentang ini, lihat /programming/3173131/redirect-copy-of-stdout-to-log-file-from-within-bash-script-itself .

Keuntungan besar dari pendekatan ini daripada alternatif adalah Anda tidak mengambil risiko perubahan pada perilaku skrip Anda dengan menyuntikkan output debug ke stdout atau stderr.

Stabledog
sumber
Lihat juga di sini tentang cara menemukan deskriptor file yang tidak digunakan untuk file tersebut.
jarno
Apakah perlu untuk menutup file descriptor (yaitu baris exec 19>&-)? Dalam pengalaman saya itu ditutup secara otomatis, ketika skrip selesai.
jarno
1
Kode yang ditunjukkan di atas tidak berasumsi bahwa Anda menjalankan skrip, atau berapa lama skrip itu, dll. Memang benar bahwa jika Anda hanya melakukan apa yang snippet ini lakukan, dan memasukkannya ke dalam skrip, pegangan file akan ditutup hanya karena seluruh shell hilang di akhir skrip. Jadi dalam hal penggunaan itu, Anda tidak perlu benar-benar menutup gagang. Tetapi secara umum ketika melakukan pengkodean terhadap sumber daya, ini adalah praktik yang baik untuk menutup apa yang telah Anda buka, karena dengan demikian kode Anda dapat digunakan dalam konteks yang lebih besar di mana urusan rumah tangga lebih penting.
Stabledog
Mengapa Anda mengekspor BASH_XTRACEFD? Mengapa tidak menetapkan nilai saja untuk itu?
jarno
Lagi pula, cara alternatif untuk menutup deskriptor file adalah dengan menetapkan nilai baru (misalnya null) untuk BASH_XTRACEFD atau menghapusnya.
jarno
4

set -xtidak mengirim apa pun ke output standar, jadi tidak ada masalah di sana. Apa yang dilakukan adalah menulis kesalahan standar, yang pergi ke konsol secara default.

Yang ingin Anda lakukan adalah mengarahkan stdout ke file lain, seperti ini:

/bin/sh -x /my/script/file 2>/my/log/file
womble
sumber
1

Lihat man tee.

Anda menjalankannya seperti itu tee commandname filenamedan itu akan menampilkan output perintah stdoutdan menulisnya juga filename.

Sven
sumber