Stdout ve stderr'ı iki ayrı akışta görüntüleme


13

Stdout ve stderr'ı görsel olarak ayırmanın bir yolunu arıyorum, böylece serpiştirilmeyecek ve kolayca tanımlanabilsinler. İdeal olarak, stdout ve stderr, ekranda farklı sütunlarda görüntülendikleri ayrı alanlara sahip olacaktır. Örneğin, şöyle görünecek çıktı:

~$ some command
some useful output info
ERROR: an error
more output
ERROR: has occurred
another message
~$ 

bunun yerine şöyle görünecektir:

~$ some command          |
some useful output info  |
more output              |  ERROR: an error
another message          |  ERROR: has occurred
~$                       |


Bu soru aynı şeyi sormuyor gibi görünüyor ve cevapların hiçbiri burada sorulanları sağlamıyor.
Michael Homer

2
Akışları iki farklı günlük dosyasına yeniden yönlendirmek ve daha sonra bunlar üzerinde MultiTail gibi bir şey kullanmak yararlı olur mu? vanheusden.com/multitail
Kusalananda

Ek açıklama çıktı yardımcı programı yararlı görünüyor mu veya çıktıyı sütun olarak mı ihtiyacınız var?
Jeff Schaller

Yanıtlar:


5

GNU'nun screendikey bölme özelliğini kullanabilirsiniz:

#! /bin/bash -
tmpdir=$(mktemp -d) || exit
trap 'rm -rf "$tmpdir"' EXIT INT TERM HUP

FIFO=$tmpdir/FIFO
mkfifo "$FIFO" || exit

conf=$tmpdir/conf

cat > "$conf" << 'EOF' || exit
split -v
focus
screen -t stderr sh -c 'tty > "$FIFO"; read done < "$FIFO"'
focus
screen -t stdout sh -c 'read tty < "$FIFO"; eval "$CMD" 2> "$tty"; echo "[Command exited with status $?, press enter to exit]"; read prompt; echo done > "$FIFO"'
EOF

CMD="$*"
export FIFO CMD

screen -mc "$conf"

Örneğin şu şekilde kullanmak için:

that-script 'ls / /not-here'

Fikir, ekranı dikey bölünmüş düzende iki ekran penceresi başlatan geçici bir conf dosyasıyla çalıştırmasıdır. İlkinde, komutunuzu stderr ikincisine bağlıyken çalıştırırız.

İkinci pencere için tty cihazını birincisine iletmek için adlandırılmış bir boru kullanırız ve ilk olarak komutun tamamlandığını ikincisine bildiririz.

Boru tabanlı yaklaşımlarla karşılaştırıldığında diğer avantaj, komutun stdout ve stderr'inin hala tty cihazlarına bağlı olmasıdır, bu nedenle arabelleğe almayı etkilemez. Her iki bölme de bağımsız olarak yukarı ve aşağı kaydırılabilir ( screen'kopyalama modu' kullanılarak ).

Bu bashkomut dosyasıyla etkileşimli gibi bir kabuk çalıştırırsanız , komut isteminin ikinci pencerede görüntüleneceğini fark edersiniz, kabuk ise ilk pencerede yazdıklarınızı okuyacak ve bu kabuklar stderr'de istemlerini çıkarır.

Durumunda bash, yankı Ayrıca ikinci pencerede görünecektir yazdıklarınıza ait eko (durumunda taleb kabuk tarafından çıkışı bash, standart hataya) de. Başka bir kabukları gibi ile ksh93, ilk pencere (gösterir yankı sen kabuk koymak sürece, terminal cihazı sürücüsü tarafından çıkış değil, kabuk) emacsya da vimod set -o emacsveya set -o vi.


1

Bu annotate-outputDebian ANNOTATE-OUTPUT (1) senaryosuna dayanan çirkin bir çözümdür . Aradığın şey olup olmadığından emin değilim ama başlamak için bir şey olabilir:

#!/bin/bash 

readonly col=150 # column to start error output 

add_out ()
{
    while IFS= read -r line; do
        echo "$1: $line"
    done
    if [ ! -z "$line" ]; then
        echo -n "$1: $line"
    fi
}

add_err ()
{
    while IFS= read -r line; do
        printf "%*s  %s %s: %s\n" $col "|" "$1" "$line"
    done
    if [ ! -z "$line" ]; then
        printf "%*s %s: %s" $col "$1" "$line"
    fi
}

cleanup() { __st=$?; rm -rf "$tmp"; exit $__st; }
trap cleanup 0
trap 'exit $?' 1 2 13 15

tmp=$(mktemp -d --tmpdir annotate.XXXXXX) || exit 1
OUT=$tmp/out
ERR=$tmp/err

mkfifo $OUT $ERR || exit 1

add_out OUTPUT < $OUT &
add_err ERROR < $ERR &

echo "I: Started $@"
"$@" > $OUT 2> $ERR ; EXIT=$?
rm -f $OUT $ERR
wait

echo "I: Finished with exitcode $EXIT"

exit $EXIT

Sen kullanarak test edebilirsiniz ./this_script another_scriptveya command.


1

Sorunuzun aşağıdaki bölümünü analiz etmeye çalışacağım:

bunun yerine şöyle görünecektir:

 ~ $ bazı komutlar
 bazı yararlı çıktı bilgileri |
 daha fazla çıktı | HATA: bir hata
 başka bir mesaj | Hata meydana geldi
 ~ $ 

Eğer biri istediğiniz şeyi parçalamak isterse:

1) stdoutAkış her satırı bir ile CR LFdeğil, '|' ile bitirir karakter. Bu, iki akışı elbette bir araya getirmez ve hizalama söz konusu değildir, çünkü stdoutelbette imkansız olan, gelecekteki satırların uzunluğunu tahmin etmek zorunda kalacaktır .

2) Hizalamayı unuttuğumuzu varsayarsak, daha stderrsonra her satırın başına "HATA:" ekleyen bir boru hattı tarafından işlendikten sonra çıktı alırız . Bu basit bir komut dosyası yaparak oldukça kolay olduğunu düşünüyorum ve stderrher zaman bu komut dosyası aracılığıyla çıkıyor emin olun .

Ama bu böyle bir çıktı yaratacaktır:

~ $ bazı komutlar
 bazı yararlı çıktı bilgileri |
 daha fazla çıktı | HATA: bir hata
 başka bir mesaj | Hata meydana geldi

Hangisi gerçekten yararlı değil, değil mi? Ayrıca inanmıyorum, o da peşindesin!

İlk soru ile ilgili sorun, bence her iki akışın eşzamansız olarak yazılabilmesi gerçeğiyle bağlantılı olarak, bir akıma eklenen her satırın seri doğasını dikkate almamanızdır.

İnanıyorum ki mümkün olan en yakın çözüm kullanmak olacaktır ncurses.
Görmek.
[ http://www.tldp.org/HOWTO/html_single/NCURSES-Programming-HOWTO/]
[ http://invisible-island.net/ncurses/ncurses-intro.html#updating]

Sonra ne olduğunuzu yapmak için, her iki akışı da tamponlamanız ve her iki tampondan eleman alan üçüncü bir tampon üretmek için birleştirmeniz gerekir. Daha sonra terminal ekranını silerek ve üçüncü tampon her değiştiğinde yeniden boyayarak üçüncü tamponu terminal ekranına dökün. Ama bu şekilde ncursesçalışıyor, neden tekerleği yeniden icat edip oradan almıyorsunuz?
Her durumda, terminal ekranının tamamen boyanma şeklini devralmanız gerekir ! Ve ekranın yeniden yazdırılan sürümündeki metni istediğiniz gibi yeniden hizalayın. Terminal karakterleri olan bir video oyunu gibi.
Umarım cevabım, neyin peşinde olduğunun sınırlarını açıklamakta yardımcı olacaktır ...
Bunu tekrarladığım için özür dilerim ama gösterdiğiniz şeyle ilgili en büyük sorun, stdoutve işlemcilerin "işlemcisi", stderrdüzgün bir şekilde hizalamak için eklenecek gelecekteki hatların uzunluğunu nasıl önceden bilecekleridir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.