Как я могу распаковать несколько файлов tar через ssh? - PullRequest
5 голосов
/ 02 июня 2011

Я пытаюсь распаковать несколько файлов tar через ssh:

ssh user@hostname "cat /dir/file*.tgz" | tar xvzf -

Вышеуказанное работает только при первом совпадении файлов на удаленном сервере.Локальный (dest) сервер получает только один файл.Подстановочный знак проверен на совпадение с несколькими файлами.

Есть ли другой способ сделать это?

Ответы [ 5 ]

4 голосов
/ 02 июня 2011

(Редактировать после первой попытки не получилось:)

Еще одна идея - избегать нескольких вызовов ssh, а также scp (поскольку для этого требуется как минимум одна поездка туда и обратно между каждым файлом):

ssh user@hostname 'tar cf - /dir/file*.tgz' | tar xf - --to-command='tar xzvf -'

Мы используем еще один tar вызов на стороне сервера, чтобы обернуть все файлы вместе, второй tar вызов на стороне клиента, чтобы снова развернуть их, который затем будет вызывать tar xzv для каждой записи один раз. Это работает аналогично base64-ответу sehe , но будет более эффективным, поскольку не взрывает файлы.

2 голосов
/ 02 июня 2011
mkdir /tmp/tars
scp 'user@hostname:/dir/file*.tgz' /tmp/tars/
foreach tarname in /tmp/tars/*.tgz; do tar xzvf "$tarname"; done

Если вы абсолютно не можете хранить временные копии:

ssh user@hostname 'ls /dir/file*.tgz' | while read tarname; 
do
    ssh user@hostname "cat '/dir/$tarname'" | tar xzvf -
done
1 голос
/ 16 мая 2012

Вы можете заключить это в вызов find и затем использовать переключатель exec для перебора каждого найденного файла.

ssh user@hostname 'find /path/to/dir -name "*.tar.gz" -exec tar xvf "{}" ";"'

Один ssh-вызов, не нужно писать bash-скрипт.

0 голосов
/ 02 июня 2011

Работать с файлами проще, чем с командами.Поэтому вместо использования команды ssh для доступа к удаленным хостам и команды tar для доступа к архивам используйте файловую систему SSHFS для доступа к файлам на удаленных хостах

mkdir hostname-dir.tmp
sshfs user@hostname:/dir hostname-dir.tmp
for a in hostname-dir.tmp/*.tgz; do tar xvf "$a"; done
fusermount -u hostname-dir.tmp

YouМожно даже пойти еще дальше и AVFS для доступа к архивам как к каталогам¹.Все это предоставлено FUSE , универсальной структурой для доступа ко всем видам вещей в виде файлов.

mountavfs
mkdir hostname-dir.tmp
sshfs user@hostname:/dir hostname-dir.tmp
for a in ~/.avfs$PWD/hostname-dir.tmp/*.tgz; do cp -Rp "$a#"/* .; done
fusermount -u hostname-dir.tmp

Если ваша оболочка - zsh, этот цикл for можно заменить на квалификатор glob .

cp -Rp ~/.avfs$PWD/hostname-dir.tmp/*.tgz(e\''reply=($REPLY\#/*)'\') .

¹ AVFS также может обращаться к удаленным файлам через SSH, но я не думаю, что вы можете получить доступ к удаленным архивам таким образом: пути AVFS имеют толькоодиночный прыжокТак что SSHFS все еще необходим.

0 голосов
/ 02 июня 2011

CarpeNoctem вдохновил меня пойти еще дальше и предложить универсальное решение, которое требует только одного ssh-соединения и выполняет все потоковое вещание.

Проверенная проверочная концепция (единый формат для удобства чтения):

 (echo '#!/bin/sh'; 
  for a in /dir/file*.tgz
  do 
      echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
      base64 "$a"
      echo "TARIMAGE"
  done) | ssh -C remote 'cd /targetdir && sh -'

Конечно, вы действительно хотите поменять местами локальные и удаленные роли, и в этом случае я бы рекомендовал вместо этого генерировать сценарий в сценарий оболочки:

gen_script.sh, chmod + x

#!/bin/bash
echo '#!/bin/sh'; 
for a in /dir/file*.tgz
do 
    echo 'base64 -d <<"TARIMAGE" | tar xvzf -'
    base64 "$a"
    echo "TARIMAGE"
done

призывание

scp gen_script.sh user@hostname:
ssh -C user@hostname /home/user/gen_script.sh | (cd targetdir && sh -)

Свободные концы, мысли:

  • вместо base64
  • вы можете включить сжатие по ssh (ssh -C) для дальнейшей оптимизации пропускной способности
  • Я сделал таргетдир / ускорился, чтобы предотвратить несчастные случаи; Вы можете отпустить, если вам это не нужно:)
...