Отправитель и получатель будут передавать файлы по ssh по запросу?
-
21-08-2019 - |
Вопрос
Я создал программу, которая перебирает множество файлов и вызывает для некоторых из них:
scp <file> user@host:<remotefile>
Однако в моем случае могут быть тысячи небольших файлов, которые необходимо перенести, и scp открывает новое ssh-соединение для каждого из них, что сопряжено с довольно большими накладными расходами.
Мне было интересно, нет ли решения, при котором я поддерживаю один запущенный процесс, который поддерживает соединение, и я могу отправлять ему "запросы" на копирование поверх отдельных файлов.
В идеале, я ищу комбинацию какой-либо программы-отправителя и программы-получателя, такую, чтобы я мог запустить один процесс (1) в начале:
ssh user@host receiverprogram
И для каждого файла я вызываю команду (2):
senderprogram <file> <remotefile>
и передайте выходные данные (2) на вход (1), и это приведет к передаче файла.В конце концов, я могу просто отправить процессу (1) некоторый сигнал для завершения.
Предпочтительно, чтобы программы-отправители и программы-получатели были программами на языке Си с открытым исходным кодом для Unix.Они могут взаимодействовать, используя сокет вместо канала, или любое другое творческое решение.
Тем не менее, это важное ограничение что каждый файл передается в тот момент, когда я выполняю итерацию по нему:недопустимо собирать список файлов, а затем вызывать один экземпляр scp
чтобы в конце перенести все файлы сразу.Кроме того, у меня есть только простой доступ оболочки к принимающему хосту.
Обновить: Я нашел решение проблемы накладных расходов на подключение, используя функции мультиплексирования ssh, смотрите мой собственный ответ ниже.Тем не менее, я начинаю розыгрыш призов, потому что мне любопытно узнать, существует ли программа-отправитель / получатель, как я описываю здесь.Кажется, должно существовать что-то, что можно использовать, напримерxmodem/ymodem/zmodem?
Решение
Этот способ сработал бы, и для других вещей этот общий подход более или менее верен.
(
iterate over file list
for each matching file
echo filename
) | cpio -H newc -o | ssh remotehost cd location \&\& | cpio -H newc -imud
Другие советы
Я нашел решение с другой стороны.С тех пор как версия 3.9, Поддержка OpenSSH мультиплексирование сеансов:одно соединение может выполнять несколько сеансов входа в систему или передачи файлов.Это позволяет избежать затрат на настройку каждого подключения.
В случае с этим вопросом я могу сначала открыть соединение с помощью настройки главного элемента управления (-M
) с розеткой (-S
) в определенном месте.Мне не нужен сеанс (-N
).
ssh user@host -M -S /tmp/%r@%h:%p -N
Далее, я могу вызвать scp
для каждого файла и проинструктируйте его использовать один и тот же сокет:
scp -o 'ControlPath /tmp/%r@%h:%p' <file> user@host:<remotefile>
Эта команда начинает копирование практически мгновенно!
Вы также можете использовать управляющий сокет для обычных ssh-подключений, которые затем немедленно откроются:
ssh user@host -S /tmp/%r@%h:%p
Если управляющий разъем больше недоступен (например,потому что вы убили мастера), это возвращает к обычному соединению.Более подробная информация доступна в эта статья.
Возможно, сработает использовать sftp вместо scp и перевести его в пакетный режим.Сделайте файл пакетной команды каналом или доменным сокетом UNIX и передавайте в него команды по мере их выполнения.
Безопасность при этом может быть немного сложной на стороне клиента.
Вы пробовали sshfs
?Ты мог бы:
sshfs remote_user@remote_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
Может быть, вы ищете это:ЗССШ
zssh (Zmodem SSH) - это программа для интерактивной передачи файлов на удаленный компьютер при использовании защищенной оболочки (ssh).Предполагается, что он станет удобной альтернативой scp, позволяющей передавать файлы без необходимости открывать другой сеанс и повторной аутентификации.
Используйте rsync через ssh, если вы можете собрать все файлы для отправки в один каталог (или иерархию каталогов).
Если у вас нет всех файлов в одном месте, пожалуйста, предоставьте дополнительную информацию о том, чего вы хотите достичь и почему вы не можете упаковать все файлы в архив и отправить его по почте.Почему так важно, чтобы каждый файл отправлялся немедленно?Было бы нормально, если бы файл был отправлен с небольшой задержкой (например, когда накопилось данных на 4 тыс.)?
Это приятная маленькая проблема.Я не знаю о готовом решении, но вы могли бы многое сделать с помощью простых сценариев оболочки.Я бы попробовал это сделать в приемнике:
#!/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
Затем, чтобы отправить файл, я бы попробовал этот скрипт
#!/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"
В конце концов вам захочется расширить скрипт, чтобы вы могли пройти через chmod
и chgrp
команды.Поскольку вы доверяете коду отправки, вероятно, проще всего структурировать это так, чтобы получатель просто вызывал shell eval
в каждой строке затем отправляйте что-то вроде
print filename='"'"$remotename"'"' > $FIFO
print "read_and_copy_bytes " '$filename' "$size" > $FIFO
а затем определите локальную функцию read_and_copy_bytes
.Правильно сформулировать цитирование - непростая задача, но в остальном все должно быть просто.
Конечно, ничего из этого не было проверено!Но я надеюсь, что это натолкнет вас на несколько полезных идей.
Похоже, это работа для вас?Передайте его выходные данные в ssh, а с другой стороны, передайте выходные данные ssh обратно в tar.
Я думаю, что рабочий стол GNOME использует одно SSH-соединение при доступе к общему ресурсу через SFTP (SSH).Я предполагаю, что это то, что происходит, потому что я вижу один SSH-процесс, когда я получаю доступ к удаленному общему ресурсу таким образом.Так что, если это правда, вы должны иметь возможность использовать ту же программу для этой цели.
Новая версия GNOME использовала GVFS через ДЖИО для того, чтобы выполнять все виды операций ввода-вывода через разные серверные части.Пакет Ubuntu gvfs-bin предоставляет различные утилиты командной строки, которые позволяют вам манипулировать серверными программами из командной строки.
Сначала вам нужно будет смонтировать вашу SSH-папку:
gvfs-крепление sftp://user@host/
И затем вы можете использовать gvfs-copy для копирования ваших файлов.Я думаю, что все передачи файлов будут выполняться через один SSH-процесс.Вы даже можете использовать ps, чтобы увидеть, какой процесс используется.
Если вы чувствуете себя более предприимчивым, вы даже можете написать свою собственную программу на C или на каком-нибудь другом языке высокого уровня, который предоставляет API для GIO.
Одним из вариантов является Раковина является ли реализация SSH-клиента и сервера написанной на Python с использованием Совмещенный рамки.Вы могли бы использовать его для написания инструмента, который принимает запросы по какому-либо другому протоколу (HTTP или доменные сокеты Unix, FTP, SSH или что-то еще) и запускает передачу файлов по длительно работающему SSH-соединению.На самом деле, у меня есть несколько готовых программ, которые используют этот метод, чтобы избежать нескольких настроек SSH-соединения.
Там был здесь очень похожий вопрос пару недель назад.Тот Самый принятый ответ предложил открыть туннель при подключении по ssh к удаленной машине и использовать этот туннель для передачи scp.
Возможно , CurlFTPFS ( кудряшки ) возможно, это подходящее решение для вас.
Похоже, что он просто подключает папку внешнего компьютера к вашему компьютеру через SFTP.Как только это будет сделано, вы сможете использовать свой обычный cp
команды, и все будет сделано надежно.
К сожалению, я не смог протестировать это сам, но дайте мне знать, если у вас это сработает!
Правка 1: Мне удалось скачать и протестировать его.Как я и опасался, для этого требуется, чтобы у клиента был FTP-сервер. Однако, Я нашел другую программу, которая имеет точно такую же концепцию, что и то, что вы ищете. sshfs
позволяет вам подключаться к вашему клиентскому компьютеру без использования какого-либо специального сервера.После того как вы смонтировали одну из их папок, вы можете использовать свой обычный cp
команды для перемещения любых файлов, которые вам нужны, в more.Как только вы закончите, это должно стать вопросом улыбки umount /path/to/mounted/folder
.Дайте мне знать, как это работает!
rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder
Это позволит использовать SSH для передачи файлов не медленным способом
Сделайте это проще, напишите небольшой скрипт-оболочку, который делает что-то вроде этого.
- проверьте файлы
- отправьте tar-файл
- унтар на другой стороне
Что - то вроде этого:
- файлы tar -cvzf test.tgz ....
- тест на scp.tgz user@other.site.com :.
- ssh user@other.site.com тест tar -xzvf.tgz
/Йохан