명령의 (거대한) 출력을 원격 시스템으로 직접 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.