unix - significado - remitente y destinatario en un sobre tamaño carta
Remitente y receptor para transferir archivos a través de ssh bajo pedido? (14)
Creé un programa que itera sobre un grupo de archivos e invoca para algunos de ellos:
scp <file> user@host:<remotefile>
Sin embargo, en mi caso, puede haber miles de pequeños archivos que necesitan ser transferidos, y scp está abriendo una nueva conexión ssh para cada uno de ellos, lo cual tiene bastante sobrecarga.
Me preguntaba si no hay solución en la que mantengo un proceso en ejecución que mantiene la conexión y puedo enviarle "solicitudes" para copiar sobre archivos individuales.
Idealmente, estoy buscando una combinación de algún programa emisor y receptor, de modo que pueda comenzar un único proceso (1) al principio:
ssh user@host receiverprogram
Y para cada archivo, invoco un comando (2):
senderprogram <file> <remotefile>
y canalice la salida de (2) a la entrada de (1), y esto haría que el archivo se transfiriera. Al final, puedo enviar el proceso (1) alguna señal para terminar.
Preferiblemente, los programas de emisor y receptor son programas de código abierto C para Unix. Se pueden comunicar usando un socket en lugar de una tubería, o cualquier otra solución creativa.
Sin embargo, es una limitación importante que cada archivo se transfiera en el momento en que lo repito: no es aceptable recopilar una lista de archivos y luego invocar una instancia de scp
para transferir todos los archivos al mismo tiempo al final. Además, solo tengo acceso de shell simple al host receptor.
Actualización: Encontré una solución para el problema de la sobrecarga de conexión usando las características de multiplexación de ssh, vea mi propia respuesta a continuación. Sin embargo, estoy comenzando una recompensa porque tengo curiosidad por encontrar si existe un programa emisor / receptor como describo aquí. Parece que debería existir algo que pueda usarse, por ejemplo, xmodem / ymodem / zmodem?
Parece un trabajo para alquitrán? Transmite su salida a ssh y, por el otro lado, transfiere la salida ssh a tar.
Podría funcionar usar sftp en lugar de scp, y colocarlo en modo de proceso por lotes. Haga que el archivo de comandos por lotes sea un conducto o un socket de dominio UNIX y alimente los comandos tal como quiera que se ejecuten.
La seguridad en esto puede ser un poco difícil en el extremo del cliente.
Use rsync en ssh si puede recopilar todos los archivos para enviar en un solo directorio (o jerarquía de directorios).
Si no tiene todos los archivos en un solo lugar, proporcione más información sobre lo que desea lograr y por qué no puede empacar todos los archivos en un archivo y enviarlos. ¿Por qué es tan vital que cada archivo se envíe de inmediato? ¿Estaría bien si el archivo se envió con un breve retraso (como cuando se acumularon 4K de datos)?
Encontré una solución desde otro ángulo. Desde la versión 3.9 , OpenSSH admite la multiplexión de sesiones : una sola conexión puede llevar múltiples sesiones de inicio de sesión o transferencia de archivos. Esto evita el costo de configuración por conexión.
Para el caso de la pregunta, primero puedo abrir una conexión con la configuración de un maestro de control ( -M
) con un socket ( -S
) en una ubicación específica. No necesito una sesión ( -N
).
ssh user@host -M -S /tmp/%r@%h:%p -N
Luego, puedo invocar scp
para cada archivo y ordenarle que use el mismo socket:
scp -o ''ControlPath /tmp/%r@%h:%p'' <file> user@host:<remotefile>
¡Este comando comienza a copiar casi instantáneamente!
También puede usar el conector de control para las conexiones ssh normales, que luego se abrirá de inmediato:
ssh user@host -S /tmp/%r@%h:%p
Si la toma de control ya no está disponible (por ejemplo, porque mató al maestro), esto vuelve a una conexión normal. Más información está disponible en este artículo .
Creo que el escritorio de GNOME utiliza una única conexión SSH al acceder a un recurso compartido a través de SFTP (SSH). Supongo que esto es lo que sucede porque veo un solo proceso SSH cuando accedo a un recurso compartido remoto de esta manera. Entonces, si esto es cierto, debería poder usar el mismo programa para este propósito.
La nueva versión de GNOME usó GVFS a través de GIO para realizar todo tipo de E / S a través de diferentes backends. El paquete de Ubuntu gvfs-bin proporciona varias utilidades de línea de comando que te permiten manipular los backends desde la línea de comando.
Primero deberá montar su carpeta SSH:
gvfs-mount sftp: // usuario @ host /
Y luego puede usar gvfs-copy para copiar sus archivos. Creo que todas las transferencias de archivos se realizarán a través de un único proceso SSH. Incluso puede usar ps para ver qué proceso se está utilizando.
Si te sientes más aventurero incluso puedes escribir tu propio programa en C o en algún otro lenguaje de alto nivel que proporcione una API a GIO.
Es un buen pequeño problema. No conozco una solución preempaquetada, pero podría hacer mucho con simples scripts de shell. Intentaría esto en el receptor:
#!/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
En el lado del remitente crearía una tubería con nombre y leería de la tubería, por ejemplo,
mkfifo $HOME/my-connection
ssh remotehost receiver-script < $HOME/my-connection
Luego, para enviar un archivo, probaría este 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
Si el tamaño del archivo es grande, probablemente no desee leerlo de una sola vez, por lo que algo del orden de
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"
Eventualmente, querrá extender el script para poder pasar los comandos chmod
y chgrp
. Como confías en el código de envío, probablemente sea más fácil estructurarlo para que el receptor simplemente llame al shell eval
en cada línea, y luego envíe cosas como
print filename=''"''"$remotename"''"'' > $FIFO
print "read_and_copy_bytes " ''$filename'' "$size" > $FIFO
y luego defina una función local read_and_copy_bytes
. Conseguir que las citas sean correctas es un oso, pero por lo demás debería ser sencillo.
Por supuesto, nada de esto ha sido probado! Pero espero que te dé algunas ideas útiles.
Mantenlo simple, escribe una pequeña secuencia de comandos envoltorio que hace algo como esto.
- tar los archivos
- enviar el archivo tar
- untar en el otro lado
Algo como esto:
- archivos tar -cvzf test.tgz ....
- scp test.tgz [email protected] :.
- ssh [email protected] tar -xzvf test.tgz
/ Johan
Puede ser que usted está buscando esto: ZSSH
zssh (Zmodem SSH) es un programa para transferir de forma interactiva archivos a una máquina remota mientras se usa el shell seguro (ssh). Está destinado a ser una alternativa conveniente a scp, lo que permite transferir archivos sin tener que abrir otra sesión y volver a autenticarse.
rsync -avlzp user@remotemachine:/path/to/files /path/to/this/folder
Esto usará SSH para transferir archivos, de una manera no lenta
Una opción es Conch es una implementación de cliente y servidor SSH escrita en Python utilizando el marco de Twsited . Puede usarlo para escribir una herramienta que acepte solicitudes a través de algún otro protocolo (HTTP o sockets de dominio Unix, FTP, SSH o lo que sea) y activa transferencias de archivos a través de una conexión SSH de larga ejecución. De hecho, tengo varios programas en producción que usan esta técnica para evitar múltiples configuraciones de conexión SSH.
¿Has probado sshfs
? Tú podrías:
sshfs remote_user@remote_host:/remote_dir /mnt/local_dir
Dónde
-
/remote_dir
era el directorio al que desea enviar archivos en el sistema al que está ingresando -
/mnt/local_dir
era la ubicación de montaje local
Con esta configuración, puede local_dir
un archivo en el local_dir
y enviarlo a través de sftp
a remote_host
en su remote_dir
Tenga en cuenta que hay una sola conexión, por lo que hay poco en el camino de la sobrecarga
Es posible que necesite usar la -o ServerAliveInterval=15
para mantener una conexión indefinida
Necesitará tener un fuse
instalado localmente y un servidor SSH compatible (y configurado para) sftp
De esta manera funcionaría, y para otras cosas, este enfoque general es más o menos correcto.
(
iterate over file list
for each matching file
echo filename
) | cpio -H newc -o | ssh remotehost cd location /&/& | cpio -H newc -imud
Perhapse CurlFTPFS podría ser una solución válida para usted.
Parece que simplemente monta la carpeta de una computadora externa en su computadora a través de SFTP. Una vez hecho esto, debería poder usar sus comandos regulares de cp
y todo se hará de forma segura.
Lamentablemente, no pude probarlo yo mismo, pero avíseme si funciona para usted.
Edición 1: he podido descargarlo y probarlo. Como temía, requiere que el cliente tenga un servidor FTP. Sin embargo , he encontrado otro programa que tiene exactamente el mismo concepto que el que está buscando. sshfs
permite conectarse a su computadora cliente sin necesidad de ningún servidor especial. Una vez que haya montado una de sus carpetas, puede usar sus comandos cp
normales para mover los archivos que necesita a más. Una vez que haya terminado, debería ser una cuestión de sonrisa de umount /path/to/mounted/folder
. ¡Déjame saber cómo funciona esto!
Hubo una pregunta muy similar aquí hace un par de semanas. La respuesta aceptada propuso abrir un túnel cuando se ssh''ing a la máquina remota y usar ese túnel para transferencias de scp.