mv-файл в / dev / null розбиває dev / null


25

Якщо я: touch file; mv file /dev/nullяк корінь, /dev/nullзникає. ls -lad /dev/nullрезультатів немає такого файлу чи каталогу. Це розбиває програми, які залежать від /dev/nullSSH, і їх можна вирішити, виконавши mknod /dev/null c 1 3; chmod 666 /dev/null. Чому переміщення звичайного файлу в цей спеціальний файл призводить до зникнення /dev/null?

Для уточнення це було для тестування, і я розумію, як mvпрацює команда. Мені цікаво те, чому ls -la /dev/nullперед заміною звичайного файлу відображається очікуваний вихід, але після цього він показує, що /dev/nullйого не існує, навіть якщо файл нібито створений за допомогою оригінальної mvкоманди, а команда файлу показує текст ASCII. Я думаю, що це має бути поєднання lsповедінки команди в поєднанні з тим, devfsколи не спеціальний файл замінює символ / спеціальний файл. Це на Mac OS X, поведінка може відрізнятися від інших ОС.


44
Не сварись /dev/null.
devnull

7
так каже @devnull
Брайам

3
Правильним способом видалення файлів є rmкоманда.
кейсі

1
Схоже, це корінь вашої проблеми, OSX devfsсмішно стосується звичайних файлів. Дивно, що ви не отримали помилки з цього приводу mv. Як щодо цього способу touch testfile; mv testfile /dev:?
Graeme

3
@Gregg, mvможе бути атомним лише в одній файловій системі.
Graeme

Відповіді:


16

Переглядаючи вихідний код для телевізора, 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, а тому , що DevFS OSX має така поведінка не-POSIX зі звичайними файлами, Apple повинна виправити їх mv.


1
Я даю цю найкращу відповідь саме зараз за надання вихідного коду та визнання цього як помилку, до чого я їхав.
Грегг Левенталь

12

Переміщення файлу до місця вже наявного файлу замінює існуючий файл. У цьому випадку /dev/nullфайл пристрою замінюється так само, як і будь-який звичайний файл. Щоб уникнути цього, використовуйте параметр -i(інтерактивний, попереджає перед перезаписом) або -n(без клоберу) варіант для mv.

/dev/nullвиконує лише свою спеціальну функцію як біт-відро, тоді пристрій відкривається як є. Наприклад, коли використовується >оператор оболонки, файл відкривається, потім усікається (не видаляється замінена, що може бути тим, що ви очікували). Як згадує casey, правильний спосіб видалення файлу - за допомогою rmабо навіть за допомогою unlink.


Дивіться мої коментарі до terdon.
Грегг Левенталь

Зрозуміли, -d було непотрібним, це лише шкідлива звичка, однак файл все-таки повинен відображатися у висновку ls, він не повинен відображатись як неіснуючий.
Грегг Левенталь

@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
Але я кажу, що / dev / null показано як відсутність під час запуску ls -lad / dev / null. Це повинно бути щось специфічне для чортів, що це те, про що я хотів знати.
Грегг Левенталь

Якщо я mv файл / dev / null, то / dev / null повинен містити файл, який міститься, але все ще існує. Хочу знати, чому це не спричинило / dev / null не знайти в ls.
Грегг Левенталь

Зрозуміло, я роблю це на Mac, тому це може бути дещо інакше, але я не очікував, що файл відобразиться як такий, що відсутній, я лише очікував, що він відобразиться як змінений у вихідному файлі.
Грегг Левенталь

@GreggLeventhal так, це повинен бути предмет OSX або BSD (будь ласка, відредагуйте свій Q та вкажіть вашу ОС). На моєму Linux я все ще бачу /dev/null, це просто файл, який я перемістив.
тердон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.