mv un file in / dev / null rompe dev / null


25

Se lo faccio: touch file; mv file /dev/nullcome root, /dev/nullscompare. ls -lad /dev/nullnon risulta in tale file o directory. Questo rompe le applicazioni che dipendono /dev/nullcome SSH e possono essere risolte facendo mknod /dev/null c 1 3; chmod 666 /dev/null. Perché lo spostamento di un file normale in questo file speciale comporta la scomparsa di /dev/null?

Per chiarire, questo era a scopo di test e capisco come funziona il mvcomando. Ciò di cui sono curioso è perché ls -la /dev/nullprima di sostituirlo con un file normale mostra l'output previsto, ma in seguito mostra che /dev/nullnon esiste anche se un file è stato presumibilmente creato tramite il mvcomando originale e il comando file mostra ASCII Text. Penso che questa debba essere una combinazione del lscomportamento del comando in combinazione con devfsquando un file non speciale sostituisce un file carattere / speciale. Questo è su Mac OS X, i comportamenti possono variare su altri SO.


44
Non scherzare /dev/null.
Devnull

7
così dice @devnull
Braiam

3
Il modo corretto di eliminare i file è il rmcomando.
Casey,

1
Sembra che sia la radice del tuo problema, OSX devfsè divertente sui file normali. Strano però non hai ricevuto un errore mv. Che ne dici di questo modo touch testfile; mv testfile /dev:?
Graeme

3
@Gregg, mvpuò essere atomico solo sullo stesso filesystem.
Graeme

Risposte:


16

Guardando il codice sorgente per 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);
}

Nel primo passaggio attraverso il ciclo while, open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)fallirà con EEXIST. Quindi /dev/nullverrà scollegato e il loop ripetuto. Ma come hai sottolineato nel tuo commento, non è possibile creare file regolari /dev, quindi al successivo passaggio attraverso il ciclo non riuscirà open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)ancora.

Presenterei una segnalazione di bug con Apple. Il mvcodice sorgente è per lo più invariato rispetto alla versione di FreeBSD, ma poiché i devfs di OSX hanno quel comportamento non POSIX con file regolari, Apple dovrebbe risolverli mv.


1
Sto dando questa migliore risposta in questo momento per fornire il codice sorgente e riconoscerlo come un bug, che è quello che stavo guidando.
Gregg Leventhal,

12

Lo spostamento di un file nella posizione di un file già esistente sostituisce il file esistente. In questo caso il /dev/nullfile del dispositivo viene sostituito, proprio come qualsiasi file normale sarebbe. Per evitare ciò, utilizzare l' opzione -i(interattivo, avvisa prima di sovrascrivere) o -n(no clober) per mv.

/dev/nullsvolge solo la sua funzione speciale di bit-bucket, quindi il dispositivo viene aperto così com'è. Ad esempio, quando >viene utilizzato l' operatore shell, il file viene aperto e quindi troncato (non rimosso e sostituito, il che potrebbe essere quello previsto). Come accennato da casey, il modo corretto di rimuovere un file è con rmo anche con unlink.


Vedi i miei commenti a Terdon.
Gregg Leventhal,

Capito, il -d non era necessario, questa è solo una cattiva abitudine, tuttavia il file dovrebbe ancora apparire nell'output ls, non dovrebbe essere mostrato come inesistente.
Gregg Leventhal,

@Graeme - benvenuti a 3K, bel lavoro!
slm

10

Umm, perché hai sovrascritto il file speciale con uno normale? Cosa ti aspettavi che succedesse? dev/nullnon è una directory, è un file che punta a un nulldispositivo. Quando fai mvqualcosa, elimini l'originale e lo sostituisci con qualsiasi cosa tu abbia spostato:

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

2
Ma sto dicendo / dev / null stava mostrando come mancante quando si esegue un ls -lad / dev / null. Questo deve essere qualcosa di specifico per i devfs, che è quello che volevo sapere.
Gregg Leventhal

Se mv file / dev / null allora / dev / null dovrebbe contenere il file contenuto ma esiste ancora. Voglio sapere perché questo non ha trovato / dev / null in un ls.
Gregg Leventhal,

Certo, lo sto facendo su un Mac, quindi potrebbe essere leggermente diverso, ma non mi aspettavo che il file mostrasse mancante, mi aspettavo solo che mostrasse come modificato nel file sorgente.
Gregg Leventhal

@GreggLeventhal sì, deve essere una cosa OSX o BSD (modifica la tua Q e specifica il tuo sistema operativo). Sul mio Linux posso ancora vedere /dev/null, è diventato il file che ho spostato.
terdon
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.