цепочечные команды для создания каталогов на удаленном сервере

2570
hornetbzz

Чтобы заставить работать rsync cronjob, мне нужно сначала создать дерево каталогов на удаленном сервере, прежде чем запускать rsync. Локальные каталоги должны быть зеркально отображены (без содержимого) на удаленном сервере. Я изо всех сил пытаюсь сделать это.

Что мне нужно, это stg, как это:

find /home/local_directories/onedir/* -type d -exec sh -c "ls -dlts {}" \; |  cut -d" " -f10 | uniq | ssh user@server mkdir -p /tmp/  

Сложность в том, как запустить последнюю трубу?

РЕДАКТИРОВАТЬ: команда rsync похожа на это (пробовал также с -R):

/usr/bin/rsync -e ssh -arz --stats --force /home/local_directories/onedir/ user@server:port:/exitsing/path/to/remote/dir/ 

Исходное дерево - это горячая копия svn (/ conf, / db, / hooks, / dav, ...)

Спасибо

0
Можете ли вы добавить команду `rsync` вместе с примером дерева каталогов исходного кода и желаемым целевым деревом каталогов? Я не знаю, нужно ли вам постоянно запускать `mkdir` на целевом хосте. Mikel 13 лет назад 0
`cut -d" "-f10`, вероятно, неправильно. Вы пытаетесь получить имя каталога? Или на что это указывает, если это символическая ссылка? Или что-то другое? Mikel 13 лет назад 0
Пожалуйста [не разбирайте `ls`] (http://mywiki.wooledge.org/ParsingLs). Dennis Williamson 13 лет назад 1
Действительно, когда мы знаем, для чего предназначен `-exec sh -c" ls -dlts {} "`, мы можем заменить его на `find -printf` или` stat` или что-то еще. Mikel 13 лет назад 0
@ Mikel, @ Dennis: я согласен, что это уродливый способ получить путь к подкаталогам из / home / local_directories / onedir hornetbzz 13 лет назад 0
`rsync` не поддерживает` user @ server: port: / path`. Вам нужен `rsync -e" ssh -p port "... user @ server: / path`. Mikel 13 лет назад 0
Я думаю, тебе лучше начать с самого начала. Четко объясните, что вы пытаетесь сделать, и мы можем помочь с решением. Mikel 13 лет назад 0
@Dennis: Большое спасибо за полезную ссылку, а также за другую замечательную ссылку, которую вы дали в другом месте об [управлении процессами] (http://mywiki.wooledge.org/ProcessManagement). hornetbzz 13 лет назад 0

2 ответа на вопрос

1
Mikel

Непонятно, зачем вам нужно использовать все эти каталоги mkdir.

Единственный каталог, который вам нужно создать, это сам каталог назначения, и это только в том случае, если он еще не существует. rsyncсоздаст все подкаталоги, если вы используете опцию -aили -v.

Примерно так должно быть достаточно:

destdir="/home/local_directories/onedir.bak" # or wherever it should go ssh user@server "mkdir \"$destdir\"" rsync -a /home/local_directories/onedir/ user@server:"$destdir" 

Или правильнее (только создание каталога, если он не существует):

destdir="/home/local_directories/onedir.bak" ssh user@server 'destdir="'"$destdir"'"; test -d "$destdir" || mkdir -p "$destdir"' rsync -a /home/local_directories/onedir/ user@server:"$destdir" 

Но если вам действительно нужно это сделать, и по какой-то причине это ls -ltds действительно необходимо, то вам придется исправить свой бит, чтобы он заработал.

Самый правильный и эффективный способ сделать последний шаг -

find ... | ssh user@server 'while IFS=$'"\n"' read -r dir; do test -d "$dir" || mkdir -p "$dir"; done' 

Идея заключается в том, что мы только начинаем findи sshодин раз. Мы начинаем findи sshвместе в конвейере, с findотправкой его вывода на удаленный сервер ssh.

findпроизводит одну строку вывода на файл, затем while readцикл на другой стороне читает по одной строке за раз и что-то делает с ней (в этом случае создает каталог).

Если вы используете xargs, он будет работать sshнесколько раз, что замедлит работу.

Лучше, но немного сложнее, это:

find ... -print0 | ssh user@server 'while read -r -d "$(printf "\000")" -r dir; do test -d "$dir" || mkdir -p "$dir"; done' 

Это лучше, потому что он обрабатывает странные символы в файлах, включая символы новой строки, которые очень редки, и плохая идея, но лучше обрабатывать их на всякий случай.


Так что, насколько я понимаю, вы должны просто делать что-то вроде:

find /home/local_directories/onedir/ -type d -print0 | ssh user@server 'while read -r -d "$(printf "\000")" -r dir; do test -d "$dir" || mkdir -p "$dir"; done' 
rsync много раз используется в многопоточном скрипте bash. В некоторых случаях происходит сбой, когда удаленное дерево каталогов не существует или, возможно, исчезло по другим причинам на удаленном сервере. hornetbzz 13 лет назад 0
Хорошо, теперь вы можете объяснить, что вы хотите `ls -dlts | вырезать -d "" -f10` делать? Есть несколько лучших способов. Mikel 13 лет назад 0
это ужасный способ получить путь к подкаталогам из / home / local_directories / onedir, на самом деле еще хуже: find / home / onedir / * -type d -exec sh -c "ls -dltsha {}" \; | cut -d "" -f10 | uniq | sed -e "s /.* onedir //" - в настоящее время борется с методом find / while, которого я не знал hornetbzz 13 лет назад 0
спасибо, это очень помогло сделать это правильно. hornetbzz 13 лет назад 0
0
Majenko

Я не совсем понимаю, чего вы пытаетесь достичь здесь. Я использую rsync все время, и мне никогда не приходилось предварительно создавать какие-либо каталоги на сервере.

rsync -avP /home/local_directories/onedir/ user@server:/where/to/sync/to/ 

следует просто отразить все дерево под onedir от локального до удаленного.

Дерево каталогов удаленного сервера может измениться в некоторых случаях. hornetbzz 13 лет назад 0
Спасибо вашему комментарию, я также проверил потоки команд rsync и мог заметить, что он НЕ должен включать порт в _user @ server: PORT_ ЕСЛИ команда связывается цепочкой ключей через ssh, иначе она терпит неудачу, говоря, что удаленный каталог не существует. hornetbzz 13 лет назад 0

Похожие вопросы