명령의 (거대한) 출력을 원격 시스템으로 직접 scp하는 방법은 무엇입니까?


50

먼저 파일을 로컬에 저장할 수 없습니다. 파일이 너무 큽니다.

이 (불명확 한) 페이지 (맨 아래로 스크롤)가 대답하는 것처럼 보이지만 테이프 드라이브와 관련된 부분을 분리하는 데 문제가 있습니다.

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

좀 더 구체적으로 만들기 위해 다음과 같이 생각할 수 있습니다 .

로컬 머신에서 :

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

(이것은 실제로 scp가 지원하지 않는 규칙을 사용하여 대신 stdin에서 가져 오기 위해 소스 파일에 대시를 대체하는 규칙을 사용합니다.)


Google 검색 결과의 URL을 게시 할 수 있습니까? 귀하의 리퍼러가 Google 인 경우 Experts Exchange는 맨 아래에 답변 만 표시합니다.
— Jon

답변:


76

ssh로 파이프하고 원격 명령을 실행할 수 있습니다. 이 경우, 원격 명령은 cat > big.txtstdin을 big.txt파일 로 복사 합니다.

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

ssh를 사용하여 원격 끝에 연결할 수있는 한 쉽고 간단합니다.

nc(NetCat)을 사용 하여 데이터를 전송할 수도 있습니다 . 수신 컴퓨터 (예 : host.example.com)에서 :

nc -l 1234 > big.txt

이 설정합니다 nc1234 포트와 해당 포트로 전송 복사 아무것도 듣고 big.txt파일. 그런 다음 보내는 기계에서 :

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

이 명령은 nc송신 측에서 수신자의 포트 1234에 연결하고 stdin의 데이터를 네트워크를 통해 복사하도록 지시합니다.

그러나이 nc솔루션에는 몇 가지 단점이 있습니다.

  • 인증이 없습니다. 누구나 포트 1234에 연결하여 파일로 데이터를 보낼 수 있습니다.
  • 데이터는에서와 같이 암호화되지 않습니다 ssh.
  • 두 시스템 중 하나가 방화벽 뒤에있는 경우, 특히 수신 측에서 연결을 통해 올바르게 라우팅하고 라우팅 할 수 있도록 선택한 포트가 열려 있어야합니다.
  • 양쪽 끝을 독립적으로 동시에 설정해야합니다. 으로 ssh솔루션, 당신은 엔드 포인트의 하나의 전송을 시작할 수 있습니다.

그것이 위안이라면, 실제로 무슨 일이 일어나고 있는지 잘 설명하기 때문에 당신이 받아 들여진 것으로 표시하는 경향이 있습니다. (정말 클린 칭을 원한다면, FIFO 파이프와 넷캣 솔루션을 왜 당신이 선호하는지에 대한 지침과 함께 포함시킬 수 있습니다! :)
— Dreeves

끝난. Netcat은 편리한 유틸리티입니다. :)
— Barry Brown

다른 의견 에서처럼 tar를 통해 배관하는 경우 공정 대체를 사용할 수 있습니다.tar -cvzf >(ssh destination 'cat > file') huge_directory_tree
— Taywee

1
SSH는 실제로 갈 길입니다. nc그것과 비교하여 기본적으로 그리고 더 중요하게는 데이터의 암호화 및 압축을 제공합니다 : 오류 감지. nc결함이있는 네트워크 드라이버와 함께 사용 하고 손상된 데이터가 감지되지 않은 상태로 전송 되는 상황이있었습니다 . SSH는 결함이있는 데이터를 해독 / 압축 해제 할 수 없기 때문에이 상황에서 실패합니다.
— jlh

15

ssh 사용 :

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

아, 예뻐요! 이 솔루션 또는 FIFO 파이프 솔루션을 선호하는 이유는 무엇입니까?
— 드림

mknod 접근 방식은 명명 된 파이프를 제외하고는 동일한 방식으로 작업을 수행한다고 생각합니다.
— bpf

4

파일을 로컬에 저장할 필요가없는 nc (Net Cat)를 사용하십시오 .


아 고마워! 내 "echo .. | scp .."예제와 동등한 내용을 포함하고 싶습니까? 그리고 다른 답변보다 이것을 선호하는 이유는 무엇입니까?
— 드림

2
나는 nc이것을 사용하지 않는 것이 좋습니다 . 한 번에 한 시스템에서 다른 시스템으로 원시 디스크 이미지를 덤프하여 네트워크 드라이버에 결함이 있고 비트가 잘못 전송되었음을 훨씬 나중에 알 수있었습니다. 사용 scp, ssh전송 오류가있을 때 당신에게 말할 것이다 다른 사람 또는 아무것도.
— jlh

2

FIFO 파이프를 사용하십시오.

mknod mypipe p
scp mypipe destination &
ls > mypipe

나는 이것을 리눅스 시스템에서 작동시킬 수 없었다. scpmypipe는 일반 파일이 아니라고 불평했습니다.
— 베리 브라운

1
같은 이유로 Mac에서도 작동하지 않았습니다. ( mkfifo하지만 파이프를 만드는 데 사용해야 했습니다.)
— Barry Brown

1
여기서도 작동하지 않았습니다. 그러나 그것이 당신을 위해 일하고 bash 또는 zsh를 가지고 있다면, 다음 예제와 같이 프로세스 대체로 이것을 더 잘 달성 할 수 있습니다.scp <(ls) destination
— Taywee

1

감사합니다 Denis Scherbakov!

Hetzner 클라우드에서 스크립트를 시도했을 때

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가 필요하지 않습니다. 리눅스 내장 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"\'"\
   "

2019.05.08 업데이트 :

요청에 따라 아래는 훨씬 간단하고 짧은 버전입니다.

#!/bin/sh

# WORKS ON LARGE FILES ONLY

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

불필요한 것들을 모두 제거하여 이것을 향상시킬 수 있습니까 scp -t? 이를 사용 방법의 최소한의 예로 정리하십시오 . 현재 환경에 맞게 사용자 정의 / 현지화 된 완전한 스크립트가 있습니다. Hetzner 위키에는 좋지만 대부분의 사람들이 scp를 통해 입력을 파이프하는 방법을 찾고있는 수퍼 유저에게는 적합하지 않습니다.
— allquixotic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.