Saya memiliki direktori dengan log kerusakan, dan saya ingin menggunakan pernyataan kondisional dalam skrip bash berdasarkan perintah find.
File log disimpan dalam format ini:
/var/log/crashes/app-2012-08-28.log
/var/log/crashes/otherapp-2012-08-28.log
Saya ingin pernyataan if hanya mengembalikan true jika ada crash log untuk aplikasi tertentu yang telah dimodifikasi dalam 5 menit terakhir. The find
perintah yang saya akan gunakan adalah:
find /var/log/crashes -name app-\*\.log -mmin -5
Saya tidak yakin bagaimana memasukkannya ke dalam if
pernyataan dengan benar. Saya pikir ini mungkin berhasil:
if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then
service myapp restart
fi
Ada beberapa area di mana saya tidak jelas:
- Saya telah melihat bendera if tapi saya tidak yakin yang mana, jika ada, yang harus saya gunakan.
- Apakah saya memerlukan
test
arahan atau haruskah saya hanya memproses terhadap hasil perintah find secara langsung, atau mungkin menggunakanfind... | wc -l
untuk mendapatkan jumlah baris sebagai gantinya? - Tidak 100% diperlukan untuk menjawab pertanyaan ini, tetapi
test
apakah untuk pengujian terhadap kode kembali yang memerintahkan pengembalian? Dan mereka agak tidak terlihat - di luarstdout
/stderr
? Saya membacaman
halaman tersebut tetapi saya masih belum jelas kapan harus digunakantest
dan bagaimana cara men-debug-nya.
find ... -exec
. Juga lihat contoh perintah di bawah Mengapa mengulangi hasil praktik buruk?... -exec command ';' -quit
, tetapi saya tidak percaya ada solusi untuk yang terakhir selain mengurai hasilnya. Juga, dalam kedua kasus, masalah utama dengan parsing hasilfind
(yaitu ketidakmampuan untuk membedakan pembatas dari karakter dalam nama file) tidak berlaku, karena Anda tidak perlu menemukan pembatas dalam kasus ini.Jawaban:
[
dantest
adalah sinonim (kecuali[
membutuhkan]
), sehingga Anda tidak ingin menggunakan[ test
:test
mengembalikan status keluar nol jika kondisinya benar, jika tidak nol. Ini sebenarnya dapat diganti oleh program apa pun untuk memeriksa status keluarnya, di mana 0 menunjukkan keberhasilan dan bukan nol menunjukkan kegagalan:Namun, semua contoh di atas hanya menguji status keluar program, dan mengabaikan output program.
Sebab
find
, Anda perlu menguji apakah ada output yang dihasilkan.-n
tes untuk string yang tidak kosong:Daftar lengkap argumen pengujian tersedia dengan memohon
help test
di barisbash
perintah.Jika Anda menggunakan
bash
(dan tidaksh
), Anda dapat menggunakan[[ condition ]]
, yang berperilaku lebih mudah ditebak ketika ada ruang atau kasus khusus lainnya dalam kondisi Anda. Kalau tidak, umumnya sama dengan menggunakan[ condition ]
. Saya telah menggunakan[[ condition ]]
dalam contoh ini, seperti yang saya lakukan sebisa mungkin.Saya juga berubah
`command`
menjadi$(command)
, yang juga umumnya berperilaku sama, tetapi lebih baik dengan perintah bersarang.sumber
echo
bisa gagal: cobaecho 'oops' > /dev/full
.find
akan keluar dengan sukses jika tidak ada kesalahan, jadi Anda tidak dapat mengandalkan status keluarnya untuk mengetahui apakah ia menemukan file. Tetapi, seperti yang Anda katakan, Anda dapat menghitung berapa banyak file yang ditemukan dan menguji nomor itu.Itu akan menjadi seperti ini:
test
(alias[
) tidak memeriksa kode kesalahan dari perintah, ini memiliki sintaks khusus untuk melakukan tes, dan kemudian keluar dengan kode kesalahan 0 jika tes berhasil, atau 1 jika tidak. Ini adalahif
salah satu yang memeriksa kode kesalahan dari perintah yang Anda berikan kepadanya, dan mengeksekusi tubuhnya berdasarkan itu.Lihat
man test
(atauhelp test
, jika Anda menggunakanbash
), danhelp if
(ditto).Dalam hal ini,
wc -l
akan menampilkan angka. Kami menggunakantest
opsi-gt
untuk menguji apakah angka itu lebih besar dari0
. Jika ya,test
(atau[
) akan kembali dengan kode keluar0
.if
akan menafsirkan kode keluar itu sebagai sukses, dan itu akan menjalankan kode di dalam tubuhnya.sumber
Ini akan menjadi
atau
Perintah
test
dan[ … ]
persis sinonim. Satu-satunya perbedaan adalah nama mereka, dan fakta yang[
membutuhkan penutupan]
sebagai argumen terakhirnya. Seperti biasa, gunakan tanda kutip ganda di sekitar substitusi perintah, jika tidak output darifind
perintah akan dipecah menjadi kata-kata, dan di sini Anda akan mendapatkan kesalahan sintaks jika ada lebih dari satu file yang cocok (dan ketika tidak ada argumen,[ -n ]
itu benar , sedangkan yang Anda inginkan[ -n "" ]
salah).Dalam ksh, bash dan zsh tetapi tidak dalam abu, Anda juga dapat menggunakan
[[ … ]]
yang memiliki aturan parsing yang berbeda:[
adalah perintah biasa, sedangkan[[ … ]]
parsing construct yang berbeda. Anda tidak perlu tanda kutip ganda di dalam[[ … ]]
(meskipun mereka tidak terluka). Anda masih memerlukan perintah;
setelah.Ini berpotensi menjadi tidak efisien: jika ada banyak file di dalam
/var/log/crashes
, find akan menjelajahi semuanya. Anda harus menghentikan pencarian segera setelah menemukan kecocokan, atau segera setelahnya. Dengan GNU find (Linux yang tidak tertanam, Cygwin), gunakan yang-quit
utama.Dengan sistem lain, pipa
find
kehead
setidaknya berhenti segera setelah pertandingan pertama (menemukan akan mati karena pipa yang rusak).(Anda dapat menggunakan
head -c 1
jikahead
perintah Anda mendukungnya.)Atau, gunakan zsh.
sumber
Ini seharusnya bekerja
sumber
adalah solusi tepat di sini.
-exec service myapp restart ';'
menyebabkanfind
untuk memanggil perintah yang ingin Anda jalankan secara langsung, daripada membutuhkan shell untuk menafsirkan apa pun.-quit
menyebabkanfind
keluar setelah memproses perintah, sehingga mencegah perintah dieksekusi lagi jika ada beberapa file yang sesuai dengan kriteria.sumber