Saya telah menjelajahi hampir semua pertanyaan serupa yang tersedia , tetapi tidak berhasil.
Izinkan saya menjelaskan masalah secara rinci:
Saya menjalankan beberapa skrip yang tidak dijaga dan ini dapat menghasilkan output standar dan garis kesalahan standar, saya ingin menangkap mereka dalam urutan yang tepat seperti yang ditampilkan oleh terminal emulator dan kemudian menambahkan awalan seperti "STDERR:" dan "STDOUT:" kepada mereka.
Saya telah mencoba menggunakan pipa dan bahkan pendekatan berbasis epoll pada mereka, tetapi tidak berhasil. Saya pikir solusi dalam penggunaan pty, meskipun saya tidak menguasai hal itu. Saya juga telah mengintip kode sumber VTE Gnome , tetapi itu belum banyak produktif.
Idealnya saya akan menggunakan Go daripada Bash untuk mencapai ini, tetapi saya belum bisa. Sepertinya pipa otomatis melarang menjaga urutan garis yang benar karena buffering.
Adakah yang bisa melakukan hal serupa? Atau itu tidak mungkin? Saya pikir jika terminal emulator dapat melakukannya, maka itu tidak - mungkin dengan membuat program C kecil yang menangani PTY (s) berbeda?
Idealnya saya akan menggunakan input asinkron untuk membaca 2 aliran ini (STDOUT dan STDERR) dan kemudian mencetak ulang kedua kebutuhan saya, tetapi urutan input sangat penting!
CATATAN: Saya mengetahui stderred tetapi tidak berfungsi untuk saya dengan skrip Bash dan tidak dapat dengan mudah diedit untuk menambahkan awalan (karena pada dasarnya membungkus banyak syscall).
Pembaruan: ditambahkan di bawah dua inti
- Contoh program yang menghasilkan stdout / stderr campuran
- Output yang diharapkan dari program di atas
(penundaan acak sub-detik dapat ditambahkan dalam skrip sampel yang saya berikan untuk membuktikan hasil yang konsisten)
Pembaruan: solusi untuk pertanyaan ini juga akan menyelesaikan pertanyaan lain ini , seperti yang ditunjukkan @Gilles. Namun saya sampai pada kesimpulan bahwa tidak mungkin melakukan apa yang diminta di sana-sini. Ketika menggunakan 2>&1
kedua aliran digabung dengan benar pada tingkat pty / pipa, tetapi untuk menggunakan aliran secara terpisah dan dalam urutan yang benar seseorang memang harus menggunakan pendekatan stderred yang melibatkan pengait syscall dan dapat dilihat sebagai kotor dalam banyak hal.
Saya akan bersemangat untuk memperbarui pertanyaan ini jika seseorang dapat menolak hal di atas.
sumber
Jawaban:
Anda mungkin menggunakan proses-proses. Wrapper sederhana yang mengumpankan kedua output dari perintah yang diberikan ke dua
sed
instance (satu untukstderr
yang lainnyastdout
), yang melakukan penandaan.Perhatikan beberapa hal:
Ini adalah mantra ajaib bagi banyak orang (termasuk saya) - karena suatu alasan (lihat jawaban terkait di bawah).
Tidak ada jaminan itu tidak akan sesekali bertukar beberapa baris - itu semua tergantung pada penjadwalan proses-proses. Sebenarnya hampir dijamin bahwa pada suatu saat akan terjadi. Yang mengatakan, jika menjaga agar pesanan tetap sama, Anda harus memproses data dari keduanya
stderr
danstdin
dalam proses yang sama, jika tidak, penjadwal kernel dapat (dan akan) mengacaukannya.Jika saya memahami masalahnya dengan benar, itu berarti Anda perlu menginstruksikan shell untuk mengalihkan kedua aliran ke satu proses (yang dapat dilakukan AFAIK). Masalahnya dimulai ketika proses itu mulai memutuskan apa yang harus ditindaklanjuti terlebih dahulu - itu harus polling kedua sumber data dan pada beberapa titik masuk ke dalam keadaan di mana ia akan memproses satu aliran dan data tiba di kedua aliran sebelum selesai. Dan di situlah ia rusak. Ini juga berarti, bahwa membungkus output syscalls seperti
stderred
mungkin adalah satu-satunya cara untuk mencapai hasil yang Anda inginkan (dan bahkan kemudian Anda mungkin memiliki masalah begitu sesuatu menjadi multithreaded pada sistem multiprosesor).Sejauh coprocesses pastikan untuk membaca jawaban Stéphane yang sangat baik di Bagaimana Anda menggunakan perintah coproc di Bash? untuk wawasan yang mendalam.
sumber
./test1.sh: 3: ./test1.sh: Syntax error: "(" unexpected
dengan menyalin / menempelkan skrip Anda)bash
dengan/bin/sh
(tidak yakin mengapa saya memilikinya di sana).eval $@
cukup buggy. Gunakan"$@"
jika Anda ingin menjalankan argumen sebagai baris perintah yang tepat - menambahkan lapisaneval
interpretasi ke sekelompok sulit diprediksi (dan berpotensi berbahaya, jika Anda meneruskan nama file atau konten lain yang tidak Anda kontrol sebagai argumen) perilaku, dan gagal mengutip bahkan lebih banyak (membagi nama dengan spasi menjadi beberapa kata, memperluas gumpalan bahkan jika mereka sebelumnya dikutip secara literal, dll).eval
menutup deskriptor file yang disebutkan dalam variabel.exec {SEDo[1]}>&-
akan bekerja apa adanya (ya, kurangnya$
sebelum{
disengaja).Metode # 1. Menggunakan deskriptor file dan awk
Bagaimana dengan sesuatu seperti ini menggunakan solusi dari SO T&J ini berjudul: Apakah ada utilitas Unix untuk menambahkan cap waktu ke baris teks? dan T&J SO ini berjudul: pipa STDOUT dan STDERR ke dua proses berbeda dalam skrip shell? .
Pendekatan
Langkah 1, kami membuat 2 fungsi di Bash yang akan melakukan pesan cap waktu ketika dipanggil:
Langkah 2 Anda akan menggunakan fungsi di atas seperti untuk mendapatkan pesan yang diinginkan:
Contoh
Di sini saya telah membuat contoh yang akan menulis
a
ke STDOUT, tidur selama 10 detik, dan kemudian menulis keluaran ke STDERR. Ketika kami menempatkan urutan perintah ini ke dalam konstruk kami di atas, kami menerima pesan seperti yang Anda tentukan.Metode # 2. Menggunakan annotate-output
Ada alat yang disebut
annotate-output
itu bagian daridevscripts
paket yang akan melakukan apa yang Anda inginkan. Satu-satunya batasan adalah ia harus menjalankan skrip untuk Anda.Contoh
Jika kita menempatkan urutan perintah contoh di atas ke dalam skrip yang disebut
mycmds.bash
seperti:Kita kemudian dapat menjalankannya seperti ini:
Format output dapat dikontrol untuk bagian cap waktu tetapi tidak lebih dari itu. Tapi ini mirip dengan apa yang Anda cari, jadi mungkin sesuai dengan tagihan.
sumber
stderred
Anda tidak dapat dengan mudah menentukan batas-batas garis (mencobanya akan menjadi retas). Saya ingin melihat apakah seseorang dapat membantu saya dengan masalah ini, tetapi ternyata semua orang ingin melepaskan satu kendala ( urutan ) yang menjadi dasar untuk pertanyaan