Saya memiliki skrip kecil, yang dipanggil setiap hari oleh crontab menggunakan perintah berikut:
/homedir/MyScript &> some_log.log
Masalah dengan metode ini adalah some_log.log hanya dibuat setelah MyScript selesai. Saya ingin memindahkan output dari program ke dalam file saat sedang berjalan sehingga saya dapat melakukan hal-hal seperti
tail -f some_log.log
dan melacak kemajuannya, dll.
sys.stdout.flush()
.Jawaban:
bash sendiri tidak akan pernah benar-benar menulis keluaran apa pun ke file log Anda. Sebaliknya, perintah yang dipanggil sebagai bagian dari skrip masing-masing akan menulis output dan menghapusnya kapan pun mereka mau. Jadi pertanyaan Anda sebenarnya adalah bagaimana memaksa perintah dalam skrip bash untuk mengosongkan, dan itu tergantung pada apa itu.
sumber
Saya menemukan solusi untuk ini di sini . Menggunakan contoh OP pada dasarnya Anda menjalankan
dan kemudian buffer dihilangkan setelah setiap baris output. Saya sering menggabungkan ini dengan
nohup
menjalankan pekerjaan lama di mesin jarak jauh.Dengan cara ini proses Anda tidak dibatalkan saat Anda keluar.
sumber
stdbuf
? Berdasarkan komentar ini sepertinya tidak tersedia di beberapa distro. Bisakah Anda menjelaskan?stdbuf
adalah bagian dari GNU coreutils, dokumentasinya dapat ditemukan di gnu.orgexport -f my_function
dan kemudianstdbuf -oL bash -c "my_function -args"
jika Anda perlu menjalankan fungsi alih-alih skripKuncinya adalah -f. Kutipan dari naskah pria:
-f, --flush Flush output after each write. This is nice for telecooperation: one person does 'mkfifo foo; script -f foo', and another can supervise real-time what is being done using 'cat foo'.
Jalankan di latar belakang:
sumber
busybox
! (cangkang saya membeku setelah itu, tapi apa pun)Anda dapat menggunakan
tee
untuk menulis ke file tanpa perlu membersihkan.sumber
Ini bukan fungsi dari
bash
, karena yang dilakukan semua shell adalah membuka file yang dipermasalahkan dan kemudian meneruskan deskriptor file sebagai output standar skrip. Yang perlu Anda lakukan adalah memastikan keluaran dihapus dari skrip Anda lebih sering daripada saat ini.Di Perl misalnya, ini dapat dilakukan dengan menyetel:
Lihat perlvar untuk informasi lebih lanjut tentang ini.
sumber
Buffering output bergantung pada bagaimana program Anda
/homedir/MyScript
diimplementasikan. Jika Anda menemukan bahwa output mendapatkan buffer, Anda harus memaksanya dalam implementasi Anda. Misalnya, gunakan sys.stdout.flush () jika itu program python atau gunakan fflush (stdout) jika itu program C.sumber
Apakah ini membantu?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
Ini akan segera menampilkan entri unik dari access.log menggunakan utilitas stdbuf .
sumber
stdbuf
tersedia di Ubuntu saat ini, tidak yakin dari mana saya mendapatkannya.stdbuf
adalah bagian daricoreutilus
(ditemukan denganapt-file search /usr/bin/stdbuf
).Masalahnya baru saja terlihat di sini adalah Anda harus menunggu program yang dijalankan dari skrip Anda menyelesaikan tugasnya.
Jika di skrip Anda, Anda menjalankan program di latar belakang Anda dapat mencoba sesuatu yang lebih.
Secara umum panggilan ke
sync
sebelum Anda keluar memungkinkan untuk membersihkan buffer sistem file dan dapat sedikit membantu.Jika dalam skrip Anda memulai beberapa program di background (
&
), Anda dapat menunggu hingga program selesai sebelum Anda keluar dari skrip. Untuk mengetahui bagaimana fungsinya bisa anda simak dibawah ini#!/bin/bash #... some stuffs ... program_1 & # here you start a program 1 in background PID_PROGRAM_1=${!} # here you remember its PID #... some other stuffs ... program_2 & # here you start a program 2 in background wait ${!} # You wait it finish not really useful here #... some other stuffs ... daemon_1 & # We will not wait it will finish program_3 & # here you start a program 1 in background PID_PROGRAM_3=${!} # here you remember its PID #... last other stuffs ... sync wait $PID_PROGRAM_1 wait $PID_PROGRAM_3 # program 2 is just ended # ...
Karena
wait
bekerja dengan pekerjaan serta denganPID
angka, solusi malas harus diletakkan di akhir skripfor job in `jobs -p` do wait $job done
Situasi yang lebih sulit adalah jika Anda menjalankan sesuatu yang menjalankan sesuatu yang lain di latar belakang karena Anda harus mencari dan menunggu (jika memang demikian) akhir dari semua proses anak : misalnya jika Anda menjalankan daemon mungkin tidak demikian untuk menunggu selesai :-).
catatan:
tunggu $ {!} berarti "tunggu sampai proses latar belakang terakhir selesai" di mana
$!
PID dari proses latar belakang terakhir. Jadi untuk meletakkanwait ${!}
setelahnyaprogram_2 &
sama dengan mengeksekusi secara langsungprogram_2
tanpa mengirimkannya di latar belakang dengan&
Dari bantuan
wait
:Syntax wait [n ...] Key n A process ID or a job specification
sumber
Terima kasih
@user3258569
, skrip mungkin satu-satunya hal yang berhasilbusybox
!Namun, cangkangnya membeku untukku setelah itu. Mencari penyebabnya, saya menemukan peringatan merah besar ini "jangan gunakan di shell non-interaktif" di halaman manual skrip :
Benar.
script -c "make_hay" -f /dev/null | grep "needle"
membekukan cangkangnya untukku.Berlawanan dengan peringatan itu, saya pikir
echo "make_hay" | script
AKAN lulus EOF, jadi saya mencobaecho "make_hay; exit" | script -f /dev/null | grep 'needle'
dan berhasil!
Perhatikan peringatan di halaman manual. Ini mungkin tidak berhasil untuk Anda.
sumber
alternatif untuk stdbuf adalah
awk '{print} END {fflush()}'
saya berharap ada bash builtin untuk melakukan ini. Biasanya itu tidak perlu, tetapi dengan versi yang lebih lama mungkin ada bug sinkronisasi bash pada deskriptor file.sumber
Saya tidak tahu apakah itu akan berhasil, tetapi bagaimana dengan menelepon
sync
?sumber
sync
adalah operasi sistem file tingkat rendah dan tidak terkait dengan keluaran yang di-buffer di tingkat aplikasi.sync
menulis buffer sistem file kotor ke penyimpanan fisik, jika perlu. Ini internal OS; aplikasi yang berjalan di atas OS selalu melihat tampilan yang koheren dari sistem file apakah blok disk telah ditulis ke penyimpanan fisik atau tidak. Untuk pertanyaan awal, aplikasi (skrip) mungkin melakukan buffering output dalam buffer internal ke aplikasi, dan OS bahkan tidak akan tahu (belum) bahwa output sebenarnya ditujukan untuk ditulis ke stdout. Jadi operasi jenis "sinkronisasi" hipotetis tidak akan bisa "menjangkau" skrip dan menarik datanya.Saya mengalami masalah ini dengan proses latar belakang di Mac OS X menggunakan
StartupItems
. Inilah cara saya mengatasinya:Jika saya membuatnya,
sudo ps aux
saya dapat melihat bahwamytool
diluncurkan.Saya menemukan bahwa (karena buffering) ketika Mac OS X dimatikan
mytool
tidak pernah mentransfer output kesed
perintah. Namun, jika saya mengeksekusisudo killall mytool
, makamytool
transfer hasilnya kesed
perintah. Oleh karena itu, saya menambahkanstop
kasus keStartupItems
yang dieksekusi saat Mac OS X dimatikan:start) if [ -x /sw/sbin/mytool ]; then # run the daemon ConsoleMessage "Starting mytool" (mytool | sed .... >> myfile.txt) & fi ;; stop) ConsoleMessage "Killing mytool" killall mytool ;;
sumber
suka atau tidak, begitulah cara kerja pengalihan.
Dalam kasus Anda, output (artinya skrip Anda telah selesai) dari skrip Anda dialihkan ke file itu.
Apa yang ingin Anda lakukan adalah menambahkan pengalihan tersebut di skrip Anda.
sumber