Saya mencoba untuk menjaga 50 baris terakhir dalam file saya di mana saya menghemat suhu setiap menit. Saya menggunakan perintah ini:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test
Tetapi hasilnya adalah file tes kosong. Saya pikir, itu akan mencantumkan 50 baris terakhir file uji dan memasukkannya ke file uji. Ketika saya menggunakan perintah ini:
tail -n 50 /home/pi/Documents/test > /home/pi/Documents/test2
itu bekerja dengan baik. Ada 50 baris dalam file test2.
Adakah yang bisa menjelaskan di mana masalahnya?
command-line
logs
tail
dorinand
sumber
sumber
logging
modulJawaban:
Masalahnya adalah shell Anda mengatur pipeline perintah sebelum menjalankan perintah. Ini bukan masalah "input dan output", melainkan bahwa konten file sudah hilang bahkan sebelum berjalan. Bunyinya seperti:
>
file output untuk menulis, memotongnyatail
.tail
berjalan, membuka/home/pi/Documents/test
dan tidak menemukan apa pun di sanaAda berbagai solusi, tetapi kuncinya adalah memahami masalahnya, apa yang sebenarnya salah dan mengapa.
Ini akan menghasilkan apa yang Anda cari,
Penjelasan:
$()
disebut substitusi perintah yang dijalankantail -n 50 /home/pi/Documents/test
> /home/pi/Documents/test
mengalihkan keluaranecho "$(tail -n 50 /home/pi/Documents/test)"
ke file yang sama.sumber
bash: xrealloc: cannot allocate 18446744071562067968 bytes
Solusi lain untuk pengalihan file membersihkan file terlebih dahulu adalah dengan menggunakan
sponge
dari paketmoreutils
seperti:sumber
Ini karena bash memproses pengalihan dengan yang
>
pertama, menghapus isi file. Kemudian ia menjalankan perintah. Jika Anda ingin menggunakannya>>
, 50 baris terakhir akan ditambahkan ke akhir dari apa yang saat ini ada dalam file. Dalam hal ini, Anda harus mengulangi 50 baris yang sama dua kali.Perintah berfungsi seperti yang diharapkan saat mengarahkan ke file yang berbeda. Berikut adalah salah satu cara untuk menulis 50 baris terakhir file ke file dengan nama yang sama:
Ini pertama menulis 50 baris terakhir ke file sementara, yang kemudian dipindahkan menggunakan
mv
untuk mengganti file asli.Seperti yang tercantum di komentar, ini tidak akan berfungsi jika file masih terbuka. Memindahkan file juga menciptakan inode baru dan dapat mengubah kepemilikan dan izin. Cara yang lebih baik untuk melakukan ini menggunakan file sementara adalah:
File sementara juga dapat dihapus, meskipun setiap kali ini terjadi isinya akan ditimpa.
sumber
tail -50 /home/pi/Documents/test >/tmp/foo && cat /tmp/foo >/home/pi/Documents/test
tail ... > temp ; cat temp > orig ; rm -f temp
bekerja.Karena Anda telah melihat masalah utama pengalihan shell, berikut adalah cara alternatif untuk memangkas file hingga 50 baris terakhir:
Kerja keras dilakukan oleh (GNU) dengan fitur
-i
"in-place editing", yang bekerja di bawah sampul dengan membuat output dalam file sementara. Sisa garis mengatur matematika untuk operasi sed, yaitu:wc
), lalu kurangi 50; tetapkan itu untukn
.n
positif, jalankan perintah sed untuk menghapus baris 1 hingga n.sumber
printf
digunakan untuk menyalurkan perintah (satu per baris) keed
. Theed
perintah adalah:1,$-50d
- hapus semua kecuali 50 baris terakhirw
- tulis file yang dimodifikasi kembali ke diskTidak ada pengalihan yang terlibat, sehingga shell tidak dapat menimpa file output sebelum dibaca.
Juga, tidak seperti kebanyakan bentuk pengeditan "di tempat" (yang biasanya hanya mensimulasikan pengeditan "di tempat" dengan membuat file temp dan kemudian mengubah nama file menjadi yang asli),
ed
sebenarnya mengedit file asli - sehingga ia menyimpan inode yang sama ( dan pemilik, grup, dan izin - tempfile + mv akan selalu mengubah inode, dan dapat mengubah yang lain tergantung pada keadaan).sumber
Pada trek yang sedikit berbeda, Anda dapat menggunakan
logrotate(8)
untuk membuat cadangan file log secara berkala ke file yang diberi nama secara bertahap, dan kemudian menghapus yang lama.Ini adalah bagaimana file log sistem utama dikelola untuk mencegahnya tumbuh terlalu lama.
sumber