Come copiare solo gli attributi di file (metadati) senza il contenuto effettivo del file?


21

Ho già copiato terabyte di file rsyncma ho dimenticato di utilizzare --archiveper conservare gli attributi speciali dei file.

Ho provato a eseguire di rsyncnuovo questa volta con --archivema era molto più lento di quanto mi aspettassi. C'è un modo semplice per farlo più velocemente copiando i metadati in modo ricorsivo?


Con "metadati" intendi le autorizzazioni e la proprietà dei file o cose più complicate come gli attributi di file estesi?
Marcel Stimberg,

Il filesystem in cui risiedono i file di origine è montato localmente o no?
enzotib,

per metadati intendo permessi e timestamp. i timestamp sono particolarmente importanti per me.
Mohammad,

il file system sia in origine che in destinazione è montato localmente.
Mohammad,

Risposte:


17

Ok, è possibile copiare proprietario, il gruppo, il permesso e timestamp utilizzando il --referenceparametro chown, chmod, touch. Ecco uno script per farlo

#!/bin/bash
# Filename: cp-metadata

myecho=echo
src_path="$1"
dst_path="$2"

find "$src_path" |
  while read src_file; do
    dst_file="$dst_path${src_file#$src_path}"
    $myecho chmod --reference="$src_file" "$dst_file"
    $myecho chown --reference="$src_file" "$dst_file"
    $myecho touch --reference="$src_file" "$dst_file"
  done

Dovresti eseguirlo con sudo(per consentire chown) e con due parametri: directory sorgente e destinazione. La sceneggiatura fa solo eco a ciò che farebbe. Se soddisfatto, cambiare la riga myecho=echocon myecho=.


1
Sì, è quello di cui ho bisogno: - reference in chmod. Grazie. E lo apprezzo davvero se qualcuno potesse introdurre qualcosa come chmod - riferimento per la copia dei timestamp.
Mohammad,

1
@Mohammad: per questo puoi usare touch --reference=otherfile file. Aggiornata la risposta
enzotib,

È fantastico. In realtà stavo leggendo il manuale del tocco proprio ora ;-)
Mohammad,

Solo una nota: touchdi progettazione cambia solo i tempi di modifica e di accesso, il tempo di "creazione" non è influenzato. (Penso che ext2 / 3 non supporti comunque la modifica di ctime, ma potrebbe importare se stai usando NTFS o simili).
Amro,

Nel caso in cui si desideri modificare solo i metadati dei file esistenti e non sia necessario garantire l'esistenza di file, aggiungere un -cinterruttore al touchcomando per interrompere la creazione di file vuoti in $dst_path.
Synchro,

5

ATTENZIONE: senza particolari soluzioni alternative, GNU cp --attributes-onlytroncherà i file di destinazione, almeno in Precise. Vedi la modifica qui sotto.

Originale:

In questa situazione probabilmente vuoi l' --attributes-onlyopzione GNU cp , insieme al --archivecodice provato e testato, fa tutti gli attributi indipendenti dal filesystem e non segue i collegamenti simbolici (seguirli può essere un male!):

cp --archive --attributes-only /source/of/failed/backup/. /destination/

Come per i file, cpè additivo con attributi estesi: se sia l'origine che la destinazione hanno attributi estesi, aggiunge gli attributi estesi dell'origine alla destinazione (anziché eliminare prima tutti gli xattr di destinazione). Mentre questo rispecchia il cpcomportamento se copi i file in un albero esistente, potrebbe non essere quello che ti aspetti.

Nota anche che se non hai conservato gli hard link per la prima volta, rsyncma vuoi conservarli ora cp , non risolverai questo problema per te; probabilmente è meglio riprovare rsynccon le giuste opzioni (vedi la mia altra risposta ) ed essere paziente.

Se hai trovato questa domanda mentre cercavi di separare e ricombinare deliberatamente i contenuti di metadati / file, allora potresti voler dare un'occhiata al metastore che si trova nei repository di Ubuntu.

Fonte: manuale GNU coreutils


Modificato per aggiungere:

cpda GNU coreutils> = 8.17 e successivi funzionerà come descritto, ma coreutils <= 8.16 troncerà i file quando ripristinano i loro metadati. In caso di dubbio, non utilizzare cpin questa situazione; usare rsynccon le giuste opzioni e / o avere pazienza.

Non lo consiglierei a meno che tu non comprenda appieno quello che stai facendo, ma a GNU precedente cppuò essere impedito di troncare i file usando il trucco LD_PRELOAD :

/*
 * File: no_trunc.c
 * Author: D.J. Capelis with minor changes by Zak Wilcox
 *
 * Compile:
 * gcc -fPIC -c -o no_trunc.o no_trunc.c
 * gcc -shared -o no_trunc.so no_trunc.o -ldl
 *
 * Use:
 * LD_PRELOAD="./no_trunc.so" cp --archive --attributes-only <src...> <dest>
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>

extern int errorno;

int (*_open)(const char *pathname, int flags, ...);
int (*_open64)(const char *pathname, int flags, ...);

int open(const char *pathname, int flags, mode_t mode) {
        _open = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
        flags &= ~(O_TRUNC);
        return _open(pathname, flags, mode);
}

int open64(const char *pathname, int flags, mode_t mode) {
        _open64 = (int (*)(const char *pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
        flags &= ~(O_TRUNC);
        return _open64(pathname, flags, mode);
}

errornodovrebbe essere errnovero?
enzotib,

Un rapido test di rimozione sembra funzionare, quindi immagino di aver perpetuato una ridondanza / errore nell'originale , ma ormai tutti saranno su coreutils più recenti.
ZakW,

ma ciò che chiami rsynccon le giuste opzioni è una risposta a un'altra domanda ...
Jean Paul,

5

Considerando la domanda come "rsync ha solo metadati da copiare, quindi perché è così lento e come posso renderlo più veloce?":

rsyncdi solito usa uguale tempo come euristico per rilevare e saltare i file invariati. Senza --archive(in particolare, senza --times) i mtime dei file di destinazione rimangono impostati sul momento in cui li hai risincronizzati, mentre i mtime dei file di origine rimangono intatti (ignorando il trucco manuale da parte tua). Senza garanzie esterne da parte tua del fatto che il contenuto dei file di origine non sia cambiato, rsync deve presumere che potrebbero esserlo e quindi deve effettuare il checksum e / o copiarlo nuovamente nella destinazione. Questo, oltre al fatto che --whole-fileè implicito per locale-> sincronizzazioni locali, rende rsyncsenza --timesapprossimativamente equivalente a cpper le sincronizzazioni locali.

A condizione che l'aggiornamento dei contenuti dei file di destinazione sia accettabile, o se i file di origine non vengono toccati dalla copia originale, si dovrebbe trovare rsync --archive --size-onlypiù veloce di un ingenuo rsync.

In caso di dubbi su ciò che rsyncsta copiando e che richiede così tanto tempo, rsync --archive --dry-run --itemize-changes ...ti dice in dettaglio esaustivo, anche se conciso.


1
Informazioni molto utili --archive --size-only è un'ottima combinazione. Non solo impedisce di ricopiare i file già esistenti nella destinazione, ma aggiornerà anche i loro metadati. Questo è stato inaspettato per me, perché la pagina man di rsync descrive --size-only come file "skipping" le cui dimensioni corrispondono. Si scopre che salta semplicemente la copia, ma sincronizzerà comunque i metadati. Ideale.
Chad von Nau,

2

Nei trasferimenti locali, quando l'origine e la destinazione si trovano su filesystem montati localmente, copieranno rsyncsempre l'intero contenuto dei file. Per evitarlo puoi usare

rsync -a --no-whole-file source dest

Ho provato rsync con --no-whole-file e --progress e posso ancora vedere l'avanzamento della copia (circa 30 MB / s); quindi immagino che non sia ancora abbastanza veloce. Sto perdendo la speranza su rsync ...
Mohammad,

Questa opzione viene utilizzata per dire di rsyncnon utilizzare il collegamento quando i file si trovano entrambi nel percorso locale, ma non impedisce rsyncdi copiare il contenuto.
Jean Paul,

2

Ho dovuto farlo da remoto su un altro computer, quindi non ho potuto usare --reference

L'ho usato per creare la sceneggiatura ...

find -printf "touch -d \"%Tc\" \"%P\"\n" >/tmp/touch.sh

Ma assicurati che non ci siano nomi di file con "in loro prima ...

find | grep '"'

Quindi copia touch.sh sul tuo computer remoto ed esegui ...

cd <DestinationFolder>; sh /tmp/touch.sh

Ci sono anche opzioni in find -printf per stampare l'utente, nome del gruppo se vuoi copiarli.


Grazie per le idee a) "usa solo uno script di shell" eb) per generare detto script usando find. Ero nella stessa situazione: ho dimenticato di copiare gli attributi, i dischi di origine e destinazione erano già su macchine diverse e non volevo davvero invertire ciò.
i336_
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.