Kirim stdout dan stderr ke file, syslog, dan terminal

8

Untuk beberapa mesin cloud yang saya luncurkan, saya mencoba masuk ke file tertentu, syslog, dan terminal / konsol.

Di bagian atas skrip pengaturan mesin / cloud-init saya, saya memiliki yang berikut:

#!/bin/bash
exec &> >(tee "/tmp/box-setup.log" | logger -t box-setup)
apt-get install -y some-package

Ini berfungsi dengan baik dalam mengirim output ke file dan syslog, tetapi tidak menyalurkan ke output ke terminal.

Secara umum tidak memiliki output terminal bukan masalah besar kecuali ketika saya debug dari konsol jarak jauh. Ketika itu terjadi, saya benar-benar buta karena konsol kosong ketika skrip bash dijalankan.

Apakah ada cara sederhana menggunakan bashredirection atau apa pun untuk menyalurkan semua output (output standar bersama dengan kesalahan standar) ke file, syslog, dan terminal secara bersamaan?

Saya menjalankan Ubuntu 16.04.

Jonathan Oliver
sumber

Jawaban:

8

Tambahkan subtitusi proses bersarang dan lainnya teedi sana seperti:

exec &> >(tee >(tee "/tmp/box-setup.log" | logger -t box-setup))

Yang pertama teedalam substitusi proses utama mengirimkan STDOUT / STDERR ke terminal dan juga ke proses substitusi bersarang, bagian teedalam yang menyimpan konten dalam file /tmp/box-setup.logdan pipa digunakan untuk mengirim output ke loggerSTDIN juga.

heemayl
sumber
Saya bingung tentang beberapa permintaan tee, itu akan bercabang untuk n stream, tidakkah ini harus setara? exec &> >(tee /tmp/box-setup.log >(logger -t box-setup))
ThorSummoner
3

Saya benar-benar buta karena konsol kosong ketika skrip bash dijalankan.

Anda mungkin ingin menyelesaikan masalah itu dengan cara yang berbeda: jalankan skrip bash Anda di latar belakang, dan jalankan less /tmp/box-setup.logdan tekan F untuk terus memperbarui layar saat baris ditambahkan ke file yang ditontonnya (seperti tail -f).

Jika menjalankan skrip di latar belakang merupakan masalah, gunakan tmuxatau screenuntuk membuat banyak sesi menjadi multipleks ke satu koneksi ssh. Gunakan lessperintah yang sama di shell lain.


Masalah aslinya:

teedapat menyalin ke beberapa tujuan. Jadikan salah satu dari mereka terminal, menggunakan /dev/ttyfile khusus. Saya pikir itu selalu mengacu pada tty mengendalikan proses saat ini. Atau mungkin lebih baik, /dev/stderrkarena teestderr masih terhubung ke stderr shell. (Ini memungkinkan Anda membungkam skrip dengan &> / dev / null).

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

BTW, ini setara dengan tetapi lebih efisien daripada (tee /dev/stderr | tee "/tmp/box-setup.log" | logger ...).

Dimungkinkan untuk menggunakan beberapa kloning file-deskriptor untuk memberikan teestdout skrip asli, daripada stderr.

Peter Cordes
sumber
1

Cukup tambahkan /dev/stderr(pilihan Anda) sebagai output tee.

exec &> >(tee /dev/stderr "/tmp/box-setup.log" | logger -t box-setup)

Output standar dan kesalahan standar akan digabungkan. Tidak ada cara untuk memisahkan mereka jika Anda ingin mempertahankan pesanan mereka, yang biasanya diinginkan. Tidak masalah jika mereka berdua pergi ke tempat yang sama (misalnya terminal).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
teestdout adalah pipa untuk logger, bukan terminal. Itu stderrpada titik itu masih terminal, berdasarkan exec &> >(tee /dev/stderr > /dev/null)bekerja seperti yang diharapkan dalam shell interaktif. stderrsepertinya ide yang lebih baik daripada ide saya /dev/tty, karena memungkinkan Anda dengan mudah menutup skrip dengan pengalihan jika Anda mau.
Peter Cordes