Отправитель и получатель для передачи файлов по ssh по запросу?

Я создал программу, которая выполняет итерацию над кучей файлов и вызывает некоторые из них:

scp <file> [email protected]:<remotefile>

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

Мне было интересно, нет ли решения, в котором я поддерживаю один процесс, поддерживающий соединение, и я могу отправить его "запросы" для копирования по отдельным файлам.

В идеале, я ищу комбинацию некоторой программы-отправителя и получателя, так что я могу начать один процесс (1) в начале:

ssh [email protected] receiverprogram

И для каждого файла я вызываю команду (2):

senderprogram <file> <remotefile>

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

Предпочтительно программы отправителя и получателя представляют собой программы с открытым кодом C для Unix. Они могут связываться с использованием сокета вместо канала или любого другого творческого решения.

Тем не менее, это важное ограничение, что каждый файл передается в момент, когда я перебираю его: недопустимо собирать список файлов, а затем вызывать один экземпляр scp для передайте все файлы сразу в конце. Кроме того, у меня есть только простой доступ оболочки к принимающему хосту.

Обновление: Я нашел решение проблемы с накладными данными соединения с использованием функций мультиплексирования ssh, см. мой собственный ответ ниже. Тем не менее, я начинаю щедрость, потому что мне интересно узнать, существует ли программа отправителя/получателя, как я описываю здесь. Кажется, что должно существовать что-то, что можно использовать, например. Xmodem/YMODEM/Zmodem?

Ответ 1

Этот способ будет работать, и, кроме всего прочего, этот общий подход более или менее прав.

(
iterate over file list
  for each matching file
   echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud

Ответ 2

Я нашел решение под другим углом. Поскольку версия 3.9, OpenSSH поддерживает мультиплексирование сеанса: одно соединение может нести несколько сеансов входа или передачи файлов. Это позволяет избежать затрат на установку для каждого соединения.

В случае вопроса я могу сначала открыть соединение с настройками мастера управления (-M) с помощью сокета (-S) в определенном месте. Мне не нужна сессия (-N).

ssh [email protected] -M -S /tmp/%[email protected]%h:%p -N

Затем я могу вызвать scp для каждого файла и дать ему указание использовать тот же сокет:

scp -o 'ControlPath /tmp/%[email protected]%h:%p' <file> [email protected]:<remotefile>

Эта команда начинает копирование почти мгновенно!

Вы также можете использовать управляющий сокет для обычных ssh-соединений, которые затем будут немедленно открываться:

ssh [email protected] -S /tmp/%[email protected]%h:%p

Если сокет управления больше не доступен (например, поскольку вы убили мастера), это возвращается к нормальному соединению. Более подробную информацию можно найти в в этой статье.

Ответ 3

Это может сработать для использования sftp вместо scp и поместить его в пакетный режим. Сделайте командный файл пакета каналом или сокет домена UNIX и кормовыми командами, как вы хотите их выполнить.

Безопасность на этом может быть немного сложной на стороне клиента.

Ответ 4

Вы пробовали sshfs? Вы могли:

sshfs [email protected]_host:/remote_dir /mnt/local_dir

Где

  • /remote_dir был каталогом, в который вы хотите отправить файлы, в систему, в которой вы находитесь, в
  • /mnt/local_dir было локальным местоположением монтирования

С помощью этой настройки вы можете просто cp создать файл в local_dir и он будет отправлен через sftp в remote_host в своем remote_dir

Обратите внимание, что существует одно соединение, поэтому накладные расходы незначительны

Вам может понадобиться использовать флаг -o ServerAliveInterval=15 для поддержки неопределенного подключения

Вам нужно будет установить fuse локально, а SSH-сервер, поддерживающий (и настроенный для) sftp

Ответ 5

Может быть, вы ищите это: ZSSH

zssh (Zmodem SSH) - это программа для интерактивной передачи файлов на удаленную машину при использовании защищенной оболочки (ssh). Он предназначен для удобной альтернативы scp, позволяющей передавать файлы без необходимости открывать другой сеанс и повторно аутентифицировать себя.

Ответ 6

Используйте rsync over ssh, если вы можете собрать все файлы для отправки в один каталог (или иерархию каталогов).

Если у вас нет всех файлов в одном месте, пожалуйста, предоставьте дополнительную информацию о том, чего вы хотите достичь, и почему вы не можете упаковать все файлы в архив и отправить их. Почему так важно, чтобы каждый файл был отправлен немедленно? Было бы хорошо, если бы файл был отправлен с небольшой задержкой (например, когда накопилось 4 тыс. Данных)?

Ответ 7

Это хорошая небольшая проблема. Я не знаю о готовом решении, но вы можете много сделать с помощью простых сценариев оболочки. Я бы попробовал это в приемнике:

#!/bin/ksh
# this is receiverprogram

while true
do
  typeset -i length
  read filename  # read filename sent by sender below
  read size      # read size of file sent
  read -N $size contents  # read all the bytes of the file
  print -n "$contents" > "$filename"
done

На стороне отправителя я создавал именованный канал и читал бы из канала, например,

mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection

Затем, чтобы отправить файл, я попробовал бы этот script

#!/bin/ksh
# this is senderprogram

FIFO=$HOME/my-connection

localname="$1"
remotename="$2"
print "$remotename" > $FIFO
size=$(stat -c %s "$localname")
print "$size" > $FIFO
cat "$localname" > $FIFO

Если размер файла большой, вы, вероятно, не хотите его читать за один раз, поэтому что-то порядка

BUFSIZ=8192

rm -f "$filename"
while ((size >= BUFSIZ)); do
  read -N $BUFSIZE buffer
  print -n "$buffer" >> "$filename"
  size=$((size - BUFSIZ))
done
read -N $size buffer
print -n "$contents" >> "$filename"

В конце концов вы захотите расширить script, чтобы вы могли проходить через команды chmod и chgrp. Поскольку вы доверяете отправляющему коду, возможно, проще всего структурировать эту вещь, чтобы получатель просто вызывал shell eval в каждой строке, а затем отправлял такие вещи, как

print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO

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

Конечно, ничего из этого не было проверено! Но я надеюсь, что это даст вам несколько полезных идей.

Ответ 8

Кажется, что работа для tar? Выведите его вывод на ssh, а с другой стороны - на выход ssh обратно в tar.

Ответ 9

Я думаю, что рабочий стол GNOME использует одно SSH-соединение при доступе к ресурсу через SFTP (SSH). Я предполагаю, что это то, что происходит, потому что я вижу один SSH-процесс, когда я получаю доступ к удаленному ресурсу таким образом. Поэтому, если это правда, вы должны иметь возможность использовать одну и ту же программу для этой цели.

Новая версия GNOME использовала GVFS через GIO, чтобы выполнять все виды ввода-вывода через разные серверы. Пакет gbfs-bin Ubuntu предоставляет различные утилит командной строки, которые позволяют вам манипулировать бэкэндами из командной строки.

Сначала вам нужно установить свою папку SSH:

gvfs-mount sftp://user @host/

И затем вы можете использовать копию gvfs для копирования ваших файлов. Я думаю, что все передачи файлов будут выполняться через один SSH-процесс. Вы даже можете использовать ps для просмотра того, какой процесс используется.

Если вы чувствуете себя более предприимчивым, вы даже можете написать свою собственную программу на C или на каком-либо другом языке высокого уровня, который предоставляет API для GIO.

Ответ 10

Один параметр Conch - это клиентская и серверная реализация SSH, написанная на Python с использованием Twsited. Вы можете использовать его для написания инструмента, который принимает запросы через какой-либо другой протокол (сокеты HTTP или Unix домена, FTP, SSH или что-то еще) и запускает передачу файлов в течение длительного использования SSH-соединения. На самом деле, у меня есть несколько программ в производстве, которые используют этот метод, чтобы избежать нескольких настроек соединения SSH.

Ответ 12

Perhapse CurlFTPFS может быть правильным решением для вас.

Похоже, он просто монтирует внешнюю папку компьютера на ваш компьютер через SFTP. После этого вы сможете использовать обычные команды cp, и все будет сделано надежно.

К сожалению, я не смог проверить это сам, но дайте мне знать, если он работает на ya!

Изменить 1: Я смог загрузить и протестировать его. Поскольку я опасаюсь, что это требует, чтобы у клиента был FTP-сервер. Однако, я нашел другую программу, которая имеет точно такое же понятие, как и то, что вы ищете. sshfs позволяет вам подключаться к вашему клиентскому компьютеру без специального сервера. После того, как вы установили одну из своих папок, вы можете использовать обычные команды cp для перемещения любых файлов, которые вам нужны, чтобы больше. После того, как вы закончите, это должно быть вопросом улыбки umount /path/to/mounted/folder. Дайте мне знать, как это получается!

Ответ 13

rsync -avlzp [email protected]:/path/to/files /path/to/this/folder

Это будет использовать SSH для передачи файлов не медленным способом.

Ответ 14

Держите его простым, напишите небольшую обертку script, которая сделает что-то вроде этого.

  • tar файлы
  • отправить tar файл
  • untar с другой стороны

Что-то вроде этого:

/Johan