67 votes

Comment puis-je scpter la sortie (énorme) d'une commande directement sur une machine distante ?

Notez que je ne peux pas d'abord stocker le fichier localement - il est trop gros.

Cette page (odieuse) (faites défiler jusqu'en bas) semble donner une réponse mais j'ai du mal à démêler la partie qui est spécifique aux lecteurs de bandes :

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

Pour rendre cela plus concret, voici comment vous pourriez le penser pourrait travail :

Sur la machine locale :

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

(C'est en utilisant la convention -- que scp ne supporte pas en fait -- de substituer un tiret au fichier source pour lui dire de le récupérer à partir de stdin à la place).

97voto

michaeljoseph Points 1494

Vous pouvez vous connecter à ssh et exécuter une commande à distance. Dans ce cas, la commande distante est cat > big.txt qui copiera stdin dans le répertoire big.txt fichier.

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

C'est simple et direct, pour autant que vous puissiez utiliser ssh pour vous connecter à l'extrémité distante.

Vous pouvez également utiliser nc (NetCat) pour transférer les données. Sur la machine réceptrice (par exemple, host.example.com) :

nc -l 1234 > big.txt

Cela va mettre en place nc d'écouter le port 1234 et de copier tout ce qui est envoyé sur ce port vers le serveur big.txt fichier. Ensuite, sur la machine d'envoi :

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

Cette commande indique nc du côté de l'émetteur pour se connecter au port 1234 du récepteur et copier les données de stdin sur le réseau.

Cependant, le nc Cette solution présente quelques inconvénients :

  • Il n'y a pas d'authentification ; n'importe qui pourrait se connecter au port 1234 et envoyer des données au fichier.
  • Les données ne sont pas cryptées, comme elles le seraient avec ssh .
  • Si l'une des deux machines se trouve derrière un pare-feu, le port choisi devra être ouvert pour permettre à la connexion de passer et d'être acheminée correctement, en particulier du côté du destinataire.
  • Les deux extrémités doivent être mises en place indépendamment et simultanément. Avec le ssh vous pouvez initier le transfert à partir d'un seul des points d'extrémité.

20voto

apsillers Points 101

En utilisant ssh :

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

5voto

Jason Anderson Points 2752

Utilisez nc (Net Cat), qui n'a pas besoin d'enregistrer le fichier localement.

4voto

Voici une solution alternative :

Tous les exemples ci-dessus suggérant ssh+cat supposent que "cat" est disponible sur le système de destination.

Dans mon cas, le système (sauvegarde Hetzner) avait un ensemble très restrictif d'outils offrant sftp, mais pas un Shell complet. L'utilisation de ssh+cat n'était donc pas possible. Je suis venu avec une solution qui utilise le drapeau non documenté "scp -t". Le Shell complet peut être trouvé ci-dessous.

#!/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"\'"\
   "

Mise à jour 2019.05.08 :

Conformément à la demande, vous trouverez ci-dessous une version beaucoup plus simple et plus courte.

#!/bin/sh

# WORKS ON LARGE FILES ONLY

cat filename.ext \
| cat <(echo 'C0600 107374182400 stdin') - \
| ssh user@host.dom 'scp -t filename.ext'

Mise à jour 2020.01.18 :

Les connexions SFTP de Hetzner se terminent assez rapidement. Pour prolonger les délais, utilisez les options ssh suivantes :

#!/bin/sh

# ...
| ssh -o TCPKeepAlive=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=3 user@host.dom 'scp -t filename.ext'

2voto

Sjoerd Points 1161

Utilisez un tube FIFO :

mknod mypipe p
scp mypipe destination &
ls > mypipe

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X