mv file ke / dev / null rusak dev / null

25

Jika saya lakukan: touch file; mv file /dev/nullsebagai root, /dev/nullmenghilang. ls -lad /dev/nulltidak menghasilkan file atau direktori seperti itu. Ini memecah aplikasi yang bergantung pada /dev/nullseperti SSH dan dapat diselesaikan dengan melakukan mknod /dev/null c 1 3; chmod 666 /dev/null. Mengapa memindahkan file biasa ke file khusus ini mengakibatkan hilangnya /dev/null?

Untuk memperjelas, ini untuk tujuan pengujian, dan saya mengerti bagaimana mvperintah itu bekerja. Yang saya ingin tahu adalah mengapa ls -la /dev/nullsebelum menggantinya dengan file biasa menunjukkan output yang diharapkan, tetapi kemudian menunjukkan bahwa /dev/nulltidak ada meskipun file itu diduga dibuat melalui mvperintah asli dan perintah file menunjukkan ASCII Text. Saya pikir ini harus merupakan kombinasi dari lsperilaku perintah bersama dengan devfsketika file non khusus menggantikan karakter / file khusus. Ini pada Mac OS X, perilaku dapat bervariasi pada OS lain.

Gregg Leventhal
sumber
44
Jangan macam-macam /dev/null.
devnull
7
demikian kata @devnull
Braiam
3
Cara yang tepat untuk menghapus file adalah rmperintah.
Casey
1
Sepertinya itu adalah akar masalah Anda, OSX devfslucu tentang file normal. Anehnya Anda tidak mendapatkan kesalahan dari itu mv. Bagaimana cara ini: touch testfile; mv testfile /dev?
Graeme
3
@ Gregg, mvhanya bisa atom pada sistem file yang sama.
Graeme

Jawaban:

16

Melihat kode sumber untuk 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);
}

Pada pass pertama melalui while loop, open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)akan gagal dengan EEXIST. Kemudian /dev/nullakan dibatalkan tautannya, dan loop diulang. Tetapi seperti yang Anda tunjukkan dalam komentar Anda, file biasa tidak dapat dibuat /dev, jadi pada putaran berikutnya melalui loop, open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)masih akan gagal.

Saya akan mengajukan laporan bug dengan Apple. The mvkode sumber sebagian besar tidak berubah dari versi FreeBSD, tetapi karena devfs OSX memiliki perilaku non-POSIX dengan file biasa, Apple harus memperbaiki mereka mv.

Tandai Plotnick
sumber
1
Saya memberikan jawaban terbaik ini sekarang untuk menyediakan kode sumber dan mengakui ini sebagai bug, yang merupakan penyebab saya mengemudi.
Gregg Leventhal
12

Memindahkan file ke lokasi file yang sudah ada menggantikan file yang ada. Dalam hal ini /dev/nullfile perangkat diganti, sama seperti file normal lainnya. Untuk menghindari hal ini, gunakan opsi -i(interaktif, peringatkan sebelum ditimpa) atau -n(tanpa clober) untuk mv.

/dev/nullhanya melakukan fungsi khusus sebagai bit-bucket maka perangkat dibuka apa adanya. Misalnya, ketika >operator shell digunakan, file dibuka kemudian dipotong (tidak dihapus diganti, yang mungkin seperti yang Anda harapkan). Seperti disebutkan oleh casey, cara yang benar untuk menghapus file adalah dengan rmatau bahkan dengan unlink.

Graeme
sumber
Lihat komentar saya untuk terdon.
Gregg Leventhal
Dipahami, -d itu tidak diperlukan, itu hanya kebiasaan yang buruk namun file tersebut masih harus muncul dalam output ls, itu seharusnya tidak ditampilkan sebagai tidak ada.
Gregg Leventhal
@Graeme - selamat datang di 3K, kerja bagus!
slm
10

Umm, karena Anda menimpa file khusus dengan yang normal? Apa yang Anda harapkan terjadi? dev/nullbukan direktori, ini adalah file yang menunjuk ke suatu nullperangkat. Ketika Anda melakukan mvsesuatu untuk itu, Anda menghapus aslinya dan menggantinya dengan apa pun yang Anda pindah:

$ file /dev/null 
/dev/null: character special 
$ sudo mv file /dev/null 
$ file /dev/null 
/dev/null: ASCII text
terdon
sumber
2
Tapi saya katakan / dev / null menunjukkan hilang ketika menjalankan ls -lad / dev / null. Ini pasti sesuatu yang spesifik untuk para devf, yang ingin saya ketahui.
Gregg Leventhal
Jika saya mv file / dev / null maka / dev / null harus berisi file apa yang terkandung tetapi masih ada. Saya ingin tahu mengapa ini menyebabkan / dev / null tidak ditemukan di ls.
Gregg Leventhal
Memang, saya melakukan ini pada Mac, jadi mungkin sedikit berbeda, tapi saya tidak berharap file tersebut akan ditampilkan sebagai hilang, saya hanya berharap itu akan ditampilkan sebagai diubah ke file sumber.
Gregg Leventhal
@ GreggLeventhal ya, itu pasti OSX atau BSD (harap edit Q Anda dan tentukan OS Anda). Di Linux saya, saya masih bisa melihat /dev/null, itu hanya menjadi file yang saya pindahkan.
terdon