rsync --delete excluiu a maioria dos arquivos no diretório de destino, por quê?

rsync --delete excluiu a maioria dos arquivos no diretório de destino, por quê?

Eu tenho meus arquivos de configuração na /etcpasta bagunçados porque não cuidei da expansão do shell ao fazer o rsync:

rsync --progress --delete -avhHe ssh /etc/logrotate.d/{httpd,mariadb,php-fpm,ppp,wpa_supplicant,yum} [email protected]:/etc

Acho que o problema é que o '.' o logrotate seguinte foi expandido e, posteriormente, algumas pastas, como /etc/httpdforam excluídas.

Quero aprender com esse erro fazendo-o corretamente. Como evito a expansão do shell ao sincronizar vários arquivos com ssh?

Responder1

Esse comando se resume a isto:

rsync --delete --recursive /etc/logrotate.d/{httpd,mariadb,php-fpm,ppp,wpa_supplicant,yum} [email protected]:/etc

O .dentro tem seu significado literal - faz parte do nome - então esse não é o problema. A parte {}está sujeita aexpansão de cinta: cada parte separada por vírgula é expandida e concatenada à parte do argumento que veio antes ( /etc/logrotate.d/). (Também receberia qualquer coisa depois, se houvesse alguma coisa: a{BC}dexpande para aBd aCd).

Portanto, este comando é equivalente a

rsync --delete --recursive /etc/logrotate.d/httpd /etc/logrotate.d/mariadb /etc/logrotate.d/php-fpm /etc/logrotate.d/ppp /etc/logrotate.d/wpa_supplicant /etc/logrotate.d/yum [email protected]:/etc

ou escolher apenas um diretório para que seja curto:

rsync --delete --recursive /etc/logrotate.d/httpd [email protected]:/etc

rsync interpreta o local "de" como uma entidade única e, se fornãoterminar com a /cria um novo arquivo ou diretório com apenas a última parte desse nome dentro do caminho de destino fornecido: aqui, é httpd. Então isso faz um /etc/httpdno destino e copia o conteúdo /etc/logrotate.d/httpdnele.

Com --delete, será entãodeletar tudoquenão foina /etc/logrotate.d/httpdfonte. O problema - já que /etc/logrotate.d/httpdprovavelmente não existe, copiá-lo e excluir todos os arquivos que não estavam presentes na fonte significaexcluindo tudo em todos esses diretórios. Se existisse, seu conteúdo não será igual ao /etc/httpd, então (quase) tudo será deletado.

Portanto, o problema é que você tem a logrotate.dparte lá, quando na verdade pretendia copiar os mesmos diretórios em /etc. O que você provavelmente quis dizer foi apenas:

rsync --progress --delete -avhHe ssh /etc/{httpd,mariadb,php-fpm,ppp,wpa_supplicant,yum} [email protected]:/etc

Isso copia /etc/httpde seu conteúdo para /etc/httpdo destino e assim por diante. Se você pretendia copiar coisas dentro logrotate.d, coloque isso no caminho em ambos os lados.

Uma coisa que você pode achar útil é o-nou --dry-runopçãopara rsync:

-n, --dry-run executa uma execução de teste sem nenhuma alteração feita

Isso mostrará uma prévia do que aconteceria, mas não fará nenhuma alteração em nenhuma das extremidades. Você pode usar isso para verificar se é o que deseja antes de executar a coisa real.


Você perguntou como evitar a expansão do shell nos argumentos que forneceu rsync. Como acima, não acho que seja isso que você deseja, dado o problema que teve, mas se precisar: as expansões de chaves não ocorrem entre aspas, portanto "a{BC}d"permanecem a{BC}dliteralmente.

informação relacionada