将文件转换为/ dev / null会破坏dev / null


25

如果我这样做:touch file; mv file /dev/null作为根,/dev/null消失。 ls -lad /dev/null导致没有这样的文件或目录。这样会破坏/dev/null像SSH 这样依赖的应用程序,并且可以通过这样做来解决mknod /dev/null c 1 3; chmod 666 /dev/null。为什么将常规文件移动到该特殊文件会导致消失/dev/null

澄清一下,这是出于测试目的,我了解该mv命令的工作原理。我很好奇的是为什么ls -la /dev/null在用常规文件替换之前会显示预期的输出,但是之后却显示/dev/null不存在,即使据称是通过原始mv命令创建的,并且file命令显示了ASCII文本。我认为这必须是ls命令行为与devfs非特殊文件替换字符/特殊文件时的组合。这是在Mac OS X上,其行为可能在其他OS上有所不同。


44
别搞砸了/dev/null
devnull 2014年

7
所以说@devnull
Braiam 2014年

3
删除文件的正确方法是rm命令。
Casey 2014年

1
似乎这是问题的根源,OSX devfs对普通文件很有趣。奇怪的是,您没有收到错误消息mv。怎么样这样:touch testfile; mv testfile /dev
Graeme

3
@Gregg,mv只能在同一文件系统上是原子的。
Graeme 2014年

Answers:


16

查看mv的源代码,http : //www.opensource.apple.com/source/file_cmds/file_cmds-220.7/mv/mv.c

/*
 * If rename fails because we're trying to cross devices, and
 * it's a regular file, do the copy internally; otherwise, use
 * cp and rm.
 */
if (lstat(from, &sb)) {
    warn("%s", from);
    return (1);
}
return (S_ISREG(sb.st_mode) ?
    fastcopy(from, to, &sb) : copy(from, to));

...

int
fastcopy(char *from, char *to, struct stat *sbp)
{
...
while ((to_fd =
    open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
        if (errno == EEXIST && unlink(to) == 0)
            continue;
        warn("%s", to);
        (void)close(from_fd);
        return (1);
}

在第一次通过while循环时,open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)将因EEXIST失败。然后/dev/null将被取消链接,并重复循环。但是,正如您在评论中指出的那样,无法在中创建常规文件/dev,因此在下一次通过循环时open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)仍然会失败。

我要向Apple提交错误报告。该mv源代码主要来自FreeBSD版本不变,但由于OSX的devfs的有规则的文件,非POSIX行为,苹果应该解决他们的mv


1
对于提供源代码并将其视为错误,我现在正在给出最佳答案,这正是我要解决的问题。
Gregg Leventhal 2014年

12

将文件移动到现有文件的位置将替换现有文件。在这种情况下,/dev/null设备文件将被替换,就像任何普通文件一样。为了避免这种情况,请为使用-i(互动,在覆盖前发出警告)或-n(禁止克隆)选项mv

/dev/null仅执行其特殊功能作为位桶,然后按原样打开设备。例如,当使用>shell运算符时,文件被打开然后被截断(未删除被替换的文件,这可能是您所期望的)。如casey所述,删除文件的正确方法是使用rm,甚至使用unlink


查看我对terdon的评论。
Gregg Leventhal 2014年

可以理解,-d是不必要的,这只是一个坏习惯,但是该文件仍应显示在ls输出中,而不应该显示为不存在。
Gregg Leventhal 2014年

@Graeme-欢迎来到3K,干得好!
slm

10

嗯,因为您用普通文件覆盖了特殊文件?您期望发生什么?dev/null不是目录,而是指向null设备的文件。当您对其mv进行处理时,将其删除,然后将其替换为移动的内容:

$ file /dev/null 
/dev/null: character special 
$ sudo mv file /dev/null 
$ file /dev/null 
/dev/null: ASCII text

2
但是我说的是/ ls / lad / dev / null在运行ls -lad / dev / null时显示为丢失。这一定是devfs特有的,这是我想知道的。
2014年

如果我mv文件/ dev / null,则/ dev / null应该包含所包含的文件,但仍然存在。我想知道为什么这会导致在ls中找不到/ dev / null。
Gregg Leventhal 2014年

当然,我是在Mac上执行此操作,因此可能会略有不同,但是我并不希望文件显示为丢失,我只是希望它显示为更改为源文件。
Gregg Leventhal 2014年

@GreggLeventhal是的,它必须是OSX或BSD(请编辑您的Q并指定您的OS)。在我的Linux上,我仍然可以看到/dev/null,它只是成为我移动的文件。
terdon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.