Apa perbedaan antara 'rm' dan 'batalkan tautan'?

55

Dengan asumsi Anda tahu targetnya adalah tautan simbolik dan bukan file, apakah ada perbedaan antara menggunakan rmdan unlinkmenghapus tautan?

IQAndreas
sumber
3
Ini dicakup dengan cukup baik pada ServerFault: serverfault.com/questions/38816/…
slm
@ slm ♦ Jawabannya sesuai dengan pertanyaan itu, tetapi pertanyaan ini berbeda, katanya: "Anggap Anda tahu targetnya adalah tautan simbolik dan bukan file".
Stéphane Gourichon
Sepertinya Anda tidak menerima jawaban di sini @IQAndreas. Silakan lakukan jika mereka membantu Anda.
Gray

Jawaban:

56

Kapan pun Anda memiliki pertanyaan seperti ini, sebaiknya Anda melakukan sedikit tes untuk melihat apa yang sebenarnya terjadi. Untuk ini, Anda dapat menggunakan strace.

batalkan tautan

$ touch file1
$ strace -s 2000 -o unlink.log unlink file1

rm

$ touch file1
$ strace -s 2000 -o rm.log rm file1

Saat Anda melihat 2 file log yang dihasilkan, Anda dapat "melihat" apa yang sebenarnya dilakukan oleh setiap panggilan.

Kerusakan

Dengan unlinkitu memanggil unlink()system call:

....
mmap(NULL, 106070960, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6d025cc000
close(3)                                = 0
unlink("file1")                         = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
....

Dengan rmjalur yang sedikit berbeda:

....
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
geteuid()                               = 1000
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0664, st_size=0, ...}, AT_SYMLINK_NOFOLLOW) = 0
faccessat(AT_FDCWD, "file1", W_OK)      = 0
unlinkat(AT_FDCWD, "file1", 0)          = 0
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
...

Sistem panggilan unlink()dan unlinkat()pada dasarnya sama kecuali perbedaan yang dijelaskan dalam halaman manual ini: http://linux.die.net/man/2/unlinkat .

kutipan

Panggilan sistem unlinkat () beroperasi dengan cara yang persis sama seperti membatalkan tautan (2) atau rmdir (2) (tergantung pada apakah flag menyertakan atau tidaknya flag AT_REMOVEDIR) kecuali perbedaan yang dijelaskan dalam halaman manual ini.

Jika pathname yang diberikan dalam pathname relatif, maka itu ditafsirkan relatif terhadap direktori yang dirujuk oleh file descriptor dirfd (bukan relatif terhadap direktori kerja saat ini dari proses pemanggilan, seperti yang dilakukan oleh unlink (2) dan rmdir (2) ) untuk nama path relatif).

Jika pathname yang diberikan dalam pathname adalah relatif dan dirfd adalah nilai khusus AT_FDCWD, maka pathname ditafsirkan relatif terhadap direktori kerja saat ini dari proses pemanggilan (seperti unlink (2) dan rmdir (2)).

Jika pathname yang diberikan dalam pathname adalah absolut, maka dirfd diabaikan.

slm
sumber
1
Karena memberi AT_FDCWD, secara efektif tidak ada perbedaan antara unlinkdan unlinkat.
Barmar
6
Itu membuat saya senang membaca jawaban ini karena saya hanya "belajar memancing" dengan cara yang kuat dan fleksibel ketika sering saya mendapatkan ikan atau kadang-kadang saya "belajar memancing" dengan cara dasar pada SO :-)
sage
22

POSIX menentukan bahwa unlinkutilitas memanggil fungsi C library unlinkdan tidak ada yang lain. Tidak ada pilihan. Jika Anda memberikan nama jalur yang valid ke sesuatu yang bukan direktori, dan jika Anda memiliki izin menulis ke direktori tempat objek itu hidup, maka unlinkakan menghapusnya.

rmadalah perintah Unix tradisional yang memiliki sedikit fungsi lain, dan tidak cukup superset unlink(lihat di bawah).

Pertama, rmmelakukan pemeriksaan keamanan. Jika Anda mencoba ke rmobjek yang Anda tidak memiliki izin menulis (yang tidak relevan dengan kemampuan Anda untuk menghapusnya: izin langsung adalah!) rmNamun menolak kecuali -fditentukan. rmbiasanya mengeluh jika file tidak ada, seperti halnya unlink; Namun dengan -f, rmtidak mengeluh. Ini sering dieksploitasi di Makefiles ( clean: @rm -f $(OBJS) ...) sehingga make cleantidak gagal ketika tidak ada yang dihapus.

Kedua, rmmemiliki -iopsi untuk mengkonfirmasi penghapusan secara interaktif.

Ketiga, rmmemiliki -runtuk menghapus direktori secara rekursif, yang merupakan sesuatu yang unlinktidak perlu dilakukan, karena fungsi C library tidak melakukan itu.

The unlinkutilitas tidak persis dilucuti-down rm. Ia melakukan subset dari apa yang rmdilakukannya, tetapi memiliki semantik yang merupakan kombinasi rm dengan -f dan rm tanpa -f .

Misalkan Anda hanya ingin menghapus file biasa terlepas dari apa izinnya sendiri. Lebih jauh, anggap Anda ingin perintah gagal jika file tidak ada, atau alasan lain. Tidak rm filejuga rm -f filememenuhi persyaratan. rm fileakan menolak jika file tidak dapat ditulisi. Tetapi rm -f fileakan lalai untuk mengeluh jika file tersebut hilang. unlink filemelakukan pekerjaan.

unlinkmungkin diperkenalkan karena rmterlalu pintar: kadang-kadang Anda hanya ingin unlinksemantik Unix murni : "tolong buat entri direktori ini hilang jika izin direktori mengizinkan" .

Kaz
sumber
2
Ini jawaban paling jelas di sini. Ini benar-benar memberikan kasus penggunaan untuk unlinkdaripada perbedaan hanya menjelaskan.
Wildcard
19

Dengan satu file, rm dan hapus tautan melakukan tugas yang sama, hapus file tersebut. Seperti yang didefinisikan POSIX, rmdan unlinkkeduanya memanggil untuk membatalkan tautan () panggilan sistem.

Dalam GNU rm, ia memanggil ke unlinkat () system call, yang setara dengan fungsi unlink()atau rmdir () kecuali dalam kasus di mana path menentukan path relatif.

Catatan

Pada beberapa sistem, unlinkbisa juga menghapus direktori. Paling tidak dalam sistem GNU, unlinktidak pernah bisa menghapus nama direktori.

cuonglm
sumber