46

Обратите внимание, что я не могу сначала сохранить файл локально - он слишком большой.

Эта (отвратительная) страница (прокручивается до конца), кажется, дает ответ, но у меня возникают проблемы при распутывании части, специфичной для ленточных накопителей:

http://webcache.googleusercontent.com/search?q=cache:lhmh960w2KQJ:www.experts-exchange.com/OS/Unix/SCO_Unix/Q_24249634.html+scp+redirect&cd=3&hl=en&ct=clnk&gl=us

Чтобы сделать это более конкретным, вот как вы думаете, это может работать:

На локальной машине:

% echo "pretend this string is a huge amt of data" | scp - remote.com:big.txt

(Это использует соглашение - которое scp на самом деле не поддерживает - заменять дефис исходным файлом, чтобы он вместо этого получал его из stdin.)

6 ответов6

73

Вы можете подключиться к ssh и запустить удаленную команду. В этом случае удаленная команда cat > big.txt которая скопирует стандартный ввод в файл big.txt .

echo "Lots of data" | ssh user@example.com 'cat > big.txt'

Это просто и понятно, если вы можете использовать ssh для подключения к удаленному концу.

Вы также можете использовать nc (NetCat) для передачи данных. На принимающем компьютере (например, host.example.com):

nc -l 1234 > big.txt

Это настроит nc на прослушивание порта 1234 и копирование всего, что отправлено на этот порт, в файл big.txt . Затем на отправляющей машине:

echo "Lots of data" | nc host.example.com 1234

Эта команда скажет nc на отправляющей стороне подключиться к порту 1234 на приемнике и скопировать данные со стандартного ввода через сеть.

Однако решение nc имеет несколько недостатков:

  • Там нет аутентификации; любой мог подключиться к порту 1234 и отправить данные в файл.
  • Данные не зашифрованы, как это было бы с ssh .
  • Если какая-либо машина находится за брандмауэром, выбранный порт должен быть открыт для правильного подключения и маршрутизации, особенно на принимающей стороне.
  • Оба конца должны быть установлены независимо и одновременно. С помощью решения ssh вы можете инициировать передачу только с одной из конечных точек.
13

Используя ssh:

echo "pretend this is a huge amt of data" | ssh user@remote.com 'cat > big.txt'
4

Используйте nc (Net Cat), которому не нужно сохранять файл локально.

3

Используйте трубу FIFO:

mknod mypipe p
scp mypipe destination &
ls > mypipe
1

Спасибо Денису Щербакову!

Когда я попробовал твой скрипт на облаке Гетцнера, я получил

debug1: Sending command: scp -v -t backup-20180420120524.tar.xz.enc
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
Transferred: sent 4168, received 2968 bytes, in 0.0 seconds
Bytes per second: sent 346786.6, received 246944.0

Но только файл без содержания был создан. Поскольку фактический контент уже зашифрован с помощью openssl, нам на самом деле не нужен scp. Встроенный в Linux ftp также обладает большими возможностями трубопровода. Итак, вот мое (все еще довольно ручное) решение:

#!/bin/bash

function join_e
{
  for word in $*; do
    echo -n "--exclude=$word "
  done
}


# Directory and file inclusion list
ILIST=(
  /home
)

# Directory and file exclusion list
ELIST=(
  var/lib/postgresql
)



export OPASS=fileencryptionpassword

nice -n 19 bash -c \
   "\
   tar $(join_e ${ELIST[@]}) -cpvf - -C / ${ILIST[*]} \
   | xz -c9e -T8 \
   | openssl enc -aes-256-cbc -pass env:OPASS \
   "

# decrypt with:
# cat backup.tar.xz.enc | openssl  aes-256-cbc -d  -pass env:OPASS | xz -dc | tar xv

# invocation procedure for ftp:
# $ ftp -np
# ftp> open storage.com
# ftp> user  storageuser storagepass
# ftp> put "| bash ~/backup.sh" backup.tar.xz.enc
1

Вот альтернативное решение:

Во всех приведенных выше примерах, предлагающих ssh+cat, предполагается, что "cat" доступна в системе назначения.

В моем случае система (резервная копия Hetzner) имела очень ограниченный набор инструментов, предлагающих sftp, но не полную оболочку. Таким образом, использование ssh+cat было невозможно. Я придумал решение, которое использует недокументированный флаг "scp -t". Полный сценарий может быть найден ниже.

#!/bin/bash

function join_e
{
  for word in $*; do
    echo -n "--exclude=$word "
  done
}

CDATE=`date +%Y%m%d%H%M%S`

# Make password available to all programs that are started by this shell.
export OPASS=YourSecretPasswrodForOpenSslEncryption

#-----------------------------------------------

# Directory and file inclusion list
ILIST=(
  var/lib
)

# Directory and file exclusion list
ELIST=(
  var/lib/postgresql
)

# 1. tar: combine all files into a single tar archive
#      a. Store files and directories in ILIST only.
#      b. Exclude files and directories from ELIST.
# 2. xz: compress as much as you can utilizing 8 threads (-T8)
# 3. openssl: encrypt contents using a password stored in OPASS local environment variable
# 4. cat: concatenate stream with SCP control message, which has to be sent before data
#      a. C0600 - create a file with 600 permissions
#      b. 107374182400 - maximum file size
#         Must be higher or equal to the actual file size.
#         Since we are dealing with STDIN, we have to make an educated guess.
#         I've set this value to 100x times my backups are.
#      c. stdin - dummy filename (unused)
# 5. ssh: connect to the server
#      a. call SCP in stdin (-t) mode.
#      b. specify destination filename

nice -n 19 bash -c \
   "\
   tar $(join_e ${ELIST[@]}) -cpf - -C / ${ILIST[*]} \
   | xz -c9e -T8 \
   | openssl enc -aes-256-cbc -pass env:OPASS \
   | cat <(echo 'C0600 107374182400 stdin') - \
   | ssh username@server.your-backup.de "\'"scp -t backup-${CDATE}.tar.xz.enc"\'"\
   "

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .