Dalam skrip bash, saya ingin menangkap keluaran standar dari baris perintah panjang demi baris, sehingga dapat dianalisis dan dilaporkan saat perintah awal masih berjalan. Ini adalah cara rumit yang bisa saya bayangkan melakukannya:
# Start long command in a separated process and redirect stdout to temp file
longcommand > /tmp/tmp$$.out &
#loop until process completes
ps cax | grep longcommand > /dev/null
while [ $? -eq 0 ]
do
#capture the last lines in temp file and determine if there is new content to analyse
tail /tmp/tmp$$.out
# ...
sleep 1 s # sleep in order not to clog cpu
ps cax | grep longcommand > /dev/null
done
Saya ingin tahu apakah ada cara yang lebih sederhana untuk melakukannya.
EDIT:
Untuk memperjelas pertanyaan saya, saya akan menambahkan ini. The longcommand
menampilkan baris status demi baris sekali per detik. Saya ingin menangkap output sebelum longcommand
selesai.
Dengan cara ini, saya berpotensi membunuh longcommand
jika tidak memberikan hasil yang saya harapkan.
Saya telah mencoba:
longcommand |
while IFS= read -r line
do
whatever "$line"
done
Tetapi whatever
(misalnya echo
) hanya dieksekusi setelah longcommand
selesai.
Jawaban:
Cukup kirimkan perintah ke
while
loop. Ada sejumlah nuansa untuk ini, tetapi pada dasarnya (dalambash
atau shell POSIX):Gotcha utama lainnya dengan ini (selain dari
IFS
hal - hal di bawah ini) adalah ketika Anda mencoba menggunakan variabel dari dalam loop setelah selesai. Ini karena loop sebenarnya dieksekusi dalam sub-shell (hanya proses shell lain) yang Anda tidak dapat mengakses variabel dari (juga selesai ketika loop tidak, di mana titik variabel benar-benar hilang. Untuk mengatasi ini, Anda dapat melakukan:Misalnya Hauke tentang pengaturan
lastpipe
dibash
solusi lain.Memperbarui
Untuk memastikan Anda memproses output dari perintah 'seperti yang terjadi', Anda dapat menggunakan
stdbuf
untuk mengatur proses 'stdout
menjadi buffer line.Ini akan mengonfigurasi proses untuk menulis satu baris pada suatu waktu ke dalam pipa alih-alih secara internal menyangga outputnya ke dalam blok. Berhati-hatilah karena program dapat mengubah pengaturan ini secara internal. Efek serupa dapat dicapai dengan
unbuffer
(bagian dariexpect
) atauscript
.stdbuf
tersedia pada sistem GNU dan FreeBSD, hanya memengaruhistdio
buffering dan hanya berfungsi untuk aplikasi non-setuid, non-setgid yang terhubung secara dinamis (karena menggunakan trik LD_PRELOAD).sumber
IFS=
diperlukan dibash
, saya memeriksa ini setelah terakhir kali.line
(dalam hal ini hasilnya dimasukkan$REPLY
tanpa spasi terkemuka dan tertinggal). Coba:echo ' x ' | bash -c 'read line; echo "[$line]"'
dan bandingkan denganecho ' x ' | bash -c 'IFS= read line; echo "[$line]"'
atauecho ' x ' | bash -c 'read; echo "[$REPLY]"'
sumber