В чем разница между «rm» и «unlink»?

55

Предполагая, что вы знаете, что целью является символическая ссылка, а не файл, есть ли разница между использованием rmи unlinkудалением ссылки?

IQAndreas
источник
3
Это довольно хорошо освещена на ServerFault: serverfault.com/questions/38816/...
ОДС
@ slm ♦ Ответы соответствуют этому вопросу, но этот вопрос отличается, он говорит: «Предполагая, что вы знаете, что цель является символической ссылкой, а не файлом».
Стефан Гурихон
Не похоже, что вы приняли ответ здесь @IQAndreas. Пожалуйста, сделайте это, если они вам помогли.
Серый

Ответы:

56

Каждый раз, когда у вас возникают подобные вопросы, лучше всего провести небольшой тест, чтобы увидеть, что на самом деле происходит. Для этого вы можете использовать strace.

Разорвать связь

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

комната

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

Когда вы посмотрите на 2 полученных файла журнала, вы сможете «увидеть», что фактически делает каждый вызов.

Сломать

При unlinkэтом вызывается unlink()системный вызов:

....
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)                           = ?
....

С rmэто немного другим путем:

....
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 +++
...

Системные вызовы unlink()и unlinkat()по сути те же самые, за исключением различий, описанных на этой странице руководства: http://linux.die.net/man/2/unlinkat .

выдержка

Системный вызов unlinkat () работает точно так же, как unlink (2) или rmdir (2) (в зависимости от того, включает ли флаг флаги AT_REMOVEDIR), за исключением различий, описанных на этой странице руководства.

Если путь, указанный в pathname, является относительным, то он интерпретируется относительно каталога, на который ссылается дескриптор файла dirfd (а не относительно текущего рабочего каталога вызывающего процесса, как это делают unlink (2) и rmdir (2). ) для относительного пути).

Если путь, указанный в pathname, является относительным, а dirfd является специальным значением AT_FDCWD, тогда имя пути интерпретируется относительно текущего рабочего каталога вызывающего процесса (например, unlink (2) и rmdir (2)).

Если путь, указанный в pathname, является абсолютным, то dirfd игнорируется.

SLM
источник
1
Поскольку он дает AT_FDCWD, фактически нет никакой разницы между unlinkи unlinkat.
Бармар
6
Мне очень приятно читать этот ответ, потому что я просто «научился ловить рыбу» мощным и гибким способом, когда я часто ловлю рыбу или иногда я «учусь ловить рыбу» основным способом на SO :-)
мудрец
22

POSIX указывает, что unlinkутилита вызывает unlinkфункцию библиотеки C и ничего больше. Это не требует выбора. Если вы передадите правильный путь к чему-то, что не является каталогом, и если у вас есть права на запись в каталог, в котором находится этот объект, он unlinkбудет удален.

rmэто традиционная команда Unix, которая имеет немного другой функциональности и не является расширенной unlink(см. ниже).

Во-первых, rmвыполняет проверки безопасности. Если вы пытаетесь rmиспользовать объект, для которого у вас нет прав на запись (что не имеет отношения к вашей способности удалить его: прямые разрешения есть!), rmТем не менее, вы отказываетесь, если -fне указано иное. rmобычно жалуется, если файл не существует, как делает unlink; Однако -f, rmне жалуется. Это часто используется в Makefiles ( clean: @rm -f $(OBJS) ...), поэтому make cleanне перестает работать, когда нечего удалять.

Во-вторых, rmесть -iвозможность интерактивного подтверждения удаления.

В- третьих, rmесть -rрекурсивно удаления каталога, которая является то , что unlinkне требуется делать, поскольку функции библиотеки C не делает этого.

unlinkУтилита точно не урезанная rm. Он выполняет подмножество того, что rmделает, но у него есть семантика, которая является комбинацией rm с -f и без rm -f.

Предположим, вы хотите просто удалить обычный файл независимо от его собственных прав доступа. Кроме того, предположим, что вы хотите, чтобы команда потерпела неудачу, если файл не существует, или по любой другой причине. Ни то, rm fileни другое не rm -f fileсоответствует требованиям. rm fileоткажется, если файл не доступен для записи. Но rm -f fileне пожалеешь, если файл отсутствует. unlink fileделает работу

unlinkвероятно, был введен потому, что rmон слишком умный: иногда вам просто нужна чистая unlinkсемантика Unix : «пожалуйста, уберите эту запись из каталога, если разрешения для каталога позволяют» .

Kaz
источник
2
Это самый ясный ответ здесь. Это фактически дает случай использования для , unlinkа не только с описанием различий.
Wildcard
19

С помощью одного файла rm и unlink выполняют одну и ту же задачу: удалите файл. Как определено POSIX, rmи unlinkоба вызова системного вызова unlink () .

В GNU rmон вызывает системный вызов unlinkat () , который эквивалентен функции unlink()or rmdir (), за исключением случая, когда path указывает относительный путь.

Запись

В некоторых системах unlinkтакже можно удалить каталог. По крайней мере, в системе GNU, unlinkникогда не можете удалить имя каталога.

cuonglm
источник