Saat ini saya menggunakan pengaturan berikut untuk mengarahkan output dari beberapa perintah:
echo "Some normal commands"
(
echo "Error: something happened"
echo "Warning: this incident will be logged"
) >> logfile
echo "More normal commands"
Ini sangat berguna, dan itu juga berfungsi dengan pipa.
Apakah ini cara terbaik untuk melakukan ini? Apakah ada alternatif yang harus saya pertimbangkan?
bash
shell-script
io-redirection
wchargin
sumber
sumber
:)
Jawaban:
Alternatifnya adalah menggunakan kawat gigi, bukan tanda kurung. Perubahan ini mengeksekusi perintah di shell saat ini , bukan di subkulit
ref: https://www.gnu.org/software/bash/manual/bashref.html#Command-Grouping
Ini sangat relevan ketika Anda memodifikasi variabel di dalam grup:
sumber
{ }
tapi tidak( )
.)(echo msg1; echo msg2)
- tetapi, dengan kawat gigi, harus{ echo msg1; echo msg2;}
, dengan spasi setelah{
dan titik koma (;
) atau ampersand (&
) sebelum}
.Jawaban Glenn adalah jawaban yang bagus - perbedaan antara
( ... )
dan{ ... }
penting.Salah satu strategi yang sering saya gunakan untuk output kesalahan seperti apa yang ada di pertanyaan Anda adalah
tee
perintah. Anda dapat melakukan sesuatu seperti ini:The
tee
perintah akan mengirim output ke dua tempat;-a
opsi "menambahkan" output ke file bernama, dan perintah juga akan meneruskan input ke stdout. Pada>&2
akhir baris mengarahkan pengalihantee
ke stderr, yang dapat ditangani secara berbeda (yaitu dalam pekerjaan cron).Satu tip lain yang sering saya gunakan dalam skrip shell adalah untuk mengubah perilaku debug atau output verbose berdasarkan apakah skrip berjalan pada terminal atau memiliki
-v
opsi yang disediakan. Sebagai contoh:Skrip dapat dimulai dengan sesuatu yang generik seperti ini di bagian atas, dengan output Verbose dan Debug tercecer di seluruh skrip. Ini hanya satu cara untuk melakukannya - ada banyak, dan orang yang berbeda akan memiliki cara mereka sendiri untuk menangani hal ini, terutama jika mereka sudah ada beberapa saat. :)
Satu lagi opsi adalah menangani output Anda dengan "handler" - fungsi shell yang dapat melakukan lebih banyak hal cerdas. Sebagai contoh:
(Perhatikan bahwa
${var^^}
hanya bash.)Ini menciptakan fungsi shell yang dapat menggunakan
syslog
fungsi sistem Anda (denganlogger
perintah) to send things to system logs. The
logme () `fungsi dapat digunakan baik dengan opsi yang menghasilkan satu baris data log, atau dengan beberapa baris input yang diproses pada stdin. Main dengannya jika tampaknya menarik.Perhatikan bahwa ini adalah contoh dan mungkin tidak boleh disalin kata demi kata kecuali Anda memahaminya dan tahu bahwa itu tepat apa yang Anda butuhkan. Ide yang lebih baik adalah mengambil konsep di sini dan mengimplementasikannya sendiri dalam skrip Anda sendiri.
sumber
function log () { cat >> $logfile }
, yang pada dasarnya adalah versi sederhana dari Andalogme
.ts(1)
; penggunaan:{ printf '%s\n' "Warning text"; printf '%s\n' "This event will be logged"; } | ts '[%Y-%m-%d %T]' | tee -a "$logfile" >&2
.ts(1)
tidak diinstal pada sistem yang saya gunakan - FreeBSD, OSX, dan kotak Ubuntu lama. Bisakah Anda memberi tahu kami apa yang menyediakannya?sponge(1)
(menulis ke file hanya setelah stdin ditutup, sehingga Anda dapat melakukannyasomething < foo | sponge foo
tanpa mengganggufoo
dengan pengalihan), danvipe(1)
(masukkan editor teks ke dalam pipa).Cara yang lebih tepat untuk melakukan ini adalah dengan
{ command; }
daripada(command)
. Alasannya adalah bahwa ketika perintah dikelompokkan dengan()
subkulit dibuka untuk mengeksekusi perintah itu dan dengan demikian variabel yang diinisialisasi selama blok itu tidak akan tersedia untuk bagian lain dari skrip.Sebaliknya ketika kita gunakan
{}
untuk pengelompokan perintah, perintah dieksekusi dalam shell yang sama dan dengan demikian variabel akan tersedia untuk bagian lain dari skrip.Di sini, ketika bagian ini dieksekusi
$var
variabel mempertahankan nilainya, sedangkan dalam kasus lain tidak akan.sumber
{ command; }
.