du memberikan dua hasil berbeda untuk file yang sama


23

Saya seorang mahasiswa pascasarjana kimia komputasi dengan akses ke cluster Linux. Cluster ini terdiri dari server file yang sangat besar (25 TB), yang terhubung dengan beberapa lusin node. Setiap node komputasi terdiri dari 8 hingga 24 core Intel Xeon. Setiap node komputasi juga mengandung disk lokal sekitar 365 TB.

Karena fileserver diakses secara rutin oleh selusin pengguna dalam grup riset, fileserver terutama digunakan untuk penyimpanan file jangka panjang (didukung setiap malam, sedangkan disk lokal node komputasi tidak pernah dicadangkan). Dengan demikian, administrator sistem telah menginstruksikan kami untuk menjalankan simulasi pada disk lokal - yang memiliki I / O lebih cepat dari server file - agar tidak memperlambat server file untuk pengguna lain.

Jadi, saya menjalankan simulasi pada disk lokal dan kemudian, setelah selesai, saya menyalin file lintasan - saya menjalankan simulasi dinamika molekul (MD) - ke server file untuk penyimpanan. Misalkan saya memiliki file lintasan yang dipanggil traj.trrdalam direktori pada disk lokal sebuah node /home/myusername/mysimulation1/traj.trr,. Untuk penyimpanan jangka panjang, saya selalu menyalin traj.trrke direktori di server file ~/mysimulation1/traj.trr,, di mana ~merupakan direktori saya di server file /export/home/myusername,. Setelah menyalinnya, maka biasanya saya gunakan du -huntuk memverifikasi yang /home/myusername/mysimulation1/traj.trrmemiliki ukuran file yang sama ~/mysimulation1/traj.trr. Dengan cara ini, setidaknya saya cukup yakin bahwa transfer ke server file berhasil. Sebagai contoh:

cd /home/myusername/mysimulation1/
cp -v traj.trr ~/mysimulation1/
du /home/myusername/mysimulation1/traj.trr -h
du ~/mysimulation1/traj.trr -h

Jika dua panggilan untuk du -hmemberikan ukuran file yang dapat dibaca oleh manusia yang sama, maka saya dapat cukup yakin bahwa transfer / salinan berhasil. ( traj.trrUkuran file tipikal saya berkisar dari sekitar 15 hingga 20 GB, tergantung pada simulasi persis yang telah saya jalankan.) Jika saya menjalankan du(yaitu, tanpa -hsaklar) pada dua traj.trrfile, ukurannya dalam byte biasanya sangat, sangat mirip - - Biasanya hanya dalam beberapa byte. Saya telah menggunakan metode keseluruhan ini selama satu setengah tahun terakhir, tanpa masalah.

Namun, baru-baru ini saya mengalami masalah berikut: kadang-kadangdu -hmelaporkan bahwa keduatraj.trrfile berbeda ukurannya beberapa GB. Berikut ini sebuah contoh:

cd /home/myusername/mysimulation1/            # this is the local disk
cp -v traj.trr ~/mysimulation1/
du traj.trr -h
cd ~/mysimulation1/                           # this is the fileserver
du traj.trr -h

Output dari dua panggilan ke du -hadalah sebagai berikut, masing-masing:

20G     traj.trr
28G     traj.trr

Saya percaya bahwa yang pertama (yaitu, traj.trrdalam disk lokal, /home/myusername/mysimulation1/) adalah ukuran file yang benar, karena lintasan simulasi saya masing-masing sekitar 15 hingga 20 GB. Tapi bagaimana mungkin file di server file sebenarnya lebih besar ? Saya bisa melihat bagaimana itu bisa lebih kecil, jika entah bagaimana cptransfer gagal. Tapi saya tidak melihat bagaimana sebenarnya bisa lebih besar .

Saya mendapatkan output yang sama ketika saya menjalankan perintah yang sama seperti di atas, tetapi tanpa -hsaklar diberikan kepada du:

20717480        traj.trr
28666688        traj.trr

Bisakah Anda memikirkan alasan untuk perbedaan itu?

Jika, karena kebetulan, duentah bagaimana tidak berfungsi, saya bisa setuju dengan itu. Tapi saya hanya perlu memastikan bahwa salinan traj.trrpada fileserver lengkap dan identik dengan versi sumbernya pada disk lokal. Saya perlu menghapus file lokal sehingga saya memiliki cukup ruang disk lokal untuk menjalankan simulasi baru, tetapi saya tidak mampu membuat versi traj.trrpada fileserver rusak.

The format file .trr (dari Gromacs dinamika molekul paket) adalah format biner, tidak teks. Jadi, saya tidak yakin apakah file dapat dibandingkan secara andal oleh program seperti diff.


5
Coba jalankan md5sumatau sha1sumpada file. Apakah mereka cocok?
cjm

2
@ cjm Saya hanya berlari md5sumdi dua file. Kedua pertandingan checksum. Jadi saya kira ini berarti kedua file itu sama?
Andrew

3
Ukuran apa yang dilaporkan oleh ls -l? Perintah dumelaporkan berapa banyak ruang pada disk yang digunakan untuk file Anda, bukan seberapa besar file Anda. Ukuran pada disk dapat dipengaruhi oleh sistem file Anda dan strategi alokasinya.
casey

2
@casey ls -l -hmengatakan bahwa kedua file berukuran 20 GB. Demikian juga, ls -lmengatakan bahwa kedua file tersebut adalah 21214683940 byte. Jadi saya kira file memiliki ukuran yang sama, tetapi jangan menggunakan jumlah ruang disk yang sama (sesuai dengan du).
Andrew

2
@Andrew mengingat ukuran yang dilaporkan oleh ls adalah sama dan hash sama, Anda dapat menyimpulkan bahwa file-nya sama. Alat-alat ini adalah apa yang memberi Anda kepercayaan diri yang Anda butuhkan dan menunjukkan kepada Anda bahwa du bukanlah alat untuk memenuhi kebutuhan Anda.
Casey

Jawaban:


32

Anda benar-benar harus menggunakan sesuatu seperti md5sumatau sha1sumuntuk memeriksa integritas.

Jika Anda benar-benar ingin menggunakan ukuran gunakan ls -latau du -b.

The duutilitas biasanya hanya menunjukkan penggunaan disk dari file, yaitu berapa banyak dari sistem file yang digunakan oleh itu. Nilai ini sepenuhnya tergantung pada sistem file dukungan dan faktor-faktor lain seperti file jarang.

Contoh:

$ truncate -s 512M foo
$ cat foo >bar
$ ls -l foo bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:06 bar
-rw-r--r-- 1 michas users 536870912 23. Dez 00:03 foo
$ du foo bar
0       foo
524288  bar
$ du -b foo bar
536870912       foo
536870912       bar

Kami memiliki dua file yang keduanya berisi 512MB nol. Yang pertama disimpan jarang dan tidak menggunakan ruang disk apa pun, sedangkan yang kedua menyimpan setiap byte secara eksplisit pada disk. - File yang sama, tetapi penggunaan disk yang sama sekali berbeda.

The -bpilihan mungkin baik untuk Anda:

   -b, --bytes
          equivalent to '--apparent-size --block-size=1'

   --apparent-size
          print apparent sizes, rather than disk usage; although the apparent
          size is  usually  smaller,  it  may  be  larger  due  to  holes  in
          ('sparse')  files, internal fragmentation, indirect blocks, and the
          like

8

Ini adalah masalah umum ketika Anda meletakkan data yang sama pada 2 HDD berbeda. Anda akan ingin menjalankan duperintah dengan dan sakelar tambahan, dengan anggapan memilikinya - yang seharusnya diberikan adalah simpul Linux.

Tombol?

   --apparent-size
          print  apparent  sizes,  rather  than  disk  usage;  although the 
          apparent size is usually smaller, it may be larger due to holes in
          ('sparse') files, internal fragmentation, indirect blocks, and the 
          like

Contoh

$ du -sh --apparent-size /home/sam/scsconfig.log ~/scsconfig.log 
93K /home/sam/scsconfig.log
93K /root/scsconfig.log

Filesystem di atas adalah disk lokal ( /root) sementara yang lain /home/samadalah bagian NFS dari NAS saya.

$ df -h . /home/sam
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      222G  118G   92G  57% /
mulder:/export/raid1/home/sam
                      917G  566G  305G  65% /home/sam

Jadi ada apa?

Ini membingungkan banyak orang, tetapi ingat bahwa ketika file disimpan ke disk, mereka mengkonsumsi blok ruang bahkan jika mereka hanya menggunakan sebagian dari blok itu. Ketika Anda menjalankan dutanpa --apparent-sizeAnda mendapatkan ukuran berdasarkan jumlah ruang blok disk yang digunakan, bukan ruang aktual yang dikonsumsi oleh file.

menggunakan checksum saja?

Ini kemungkinan merupakan opsi yang lebih baik jika Anda khawatir tentang membandingkan 2 pohon file. Anda dapat menggunakan perintah ini untuk menghitung checksum untuk semua file, dan kemudian menghitung checksum checksum terakhir. Contoh ini menggunakan sha1sumtetapi Anda bisa dengan mudah menggunakannya md5sum.

$ cd /some/dir
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum

Contoh

$ cd ~/dir1
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

$ cd ~/dir2
$ find . -type f \( -exec sha1sum "{}" \; \) | sort -k2,2 | sha1sum
55e2672f8d6fccff6d83f0bffba1b67aeab87911  -

Jadi kita dapat melihat bahwa 2 pohon itu identik.

(Catatan: perintah find akan mencantumkan file ketika muncul di sistem file. Jadi, jika Anda membandingkan dua direktori dari sistem file yang berbeda (mis. Ext3 vs. APFS), Anda perlu mengurutkan terlebih dahulu sebelum sha1sum akhir. (Ditambahkan oleh Xianjun Dong)


5

Jawaban singkat: jangan menguji ukuran file, uji status pengembalian perintah. Status pengembalian satu-satunya indikasi yang dapat diandalkan apakah salinan berhasil (pendek membandingkan dua file byte demi byte, secara langsung tidak langsung - yang berlebihan jika salinan berhasil).

Memeriksa ukuran file bukanlah cara yang sangat berguna untuk memeriksa apakah salinan berhasil. Dalam beberapa kasus, ini mungkin merupakan pemeriksaan kewarasan yang berguna, misalnya ketika Anda mengunduh file dari web. Tapi di sini ada cara yang lebih baik.

Semua perintah Unix mengembalikan status untuk menunjukkan apakah mereka berhasil: 0 untuk sukses, 1 atau lebih untuk kesalahan. Jadi periksa status keluar dari cp. cpbiasanya akan mencetak pesan kesalahan jika gagal, menunjukkan apa kesalahannya. Dalam skrip, status keluar dari perintah terakhir ada di variabel ajaib $?.

cp -v traj.trr ~/mysimulation1/
if [ $? -ne 0 ]; then
  echo 1>&2 "cp failed due to the error above"
  exit 2
 fi

Alih-alih memeriksa apakah $?nol, Anda dapat menggunakan operator boolean.

cp -v traj.trr ~/mysimulation1/ || exit 2

Jika Anda menjalankan skrip dan ingin skrip berhenti jika ada perintah gagal, jalankan set -e. Jika ada perintah yang gagal (yaitu mengembalikan status bukan nol), skrip akan segera keluar dengan status yang sama dengan perintah.

set -e
…
cp -v traj.trr ~/mysimulation1/

Adapun alasan file yang Anda salin lebih besar, itu pasti karena itu adalah file yang jarang . File jarang adalah bentuk kompresi kasar di mana blok yang hanya berisi byte nol tidak disimpan. Ketika Anda menyalin file, cpperintah membaca dan menulis nol byte, jadi di mana aslinya memiliki blok yang hilang, salinan memiliki blok yang penuh dengan byte nol. Di Linux, cpperintah mencoba mendeteksi file jarang, tetapi tidak selalu berhasil; cp --sparse=alwaysmembuatnya berusaha lebih keras dengan mengorbankan sedikit peningkatan waktu CPU.

Lebih umum, dudapat mengembalikan hasil yang berbeda karena bentuk kompresi lainnya. Sistem file terkompresi jarang terjadi. Jika Anda ingin mengetahui ukuran file seperti dalam jumlah byte dalam file, berbeda dengan jumlah blok disk yang digunakannya, gunakan ls -lsebagai ganti du.


Terima kasih banyak! Apakah Anda tahu jika ada utilitas (terpisah) yang dapat memberi tahu saya apakah file saya jarang atau tidak?
Andrew

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.