검색할 수 없는 스트림(미리 크기를 알 수 없음)을 결합하고 다시 분리할 수 있는 프로그램이 있습니까?

검색할 수 없는 스트림(미리 크기를 알 수 없음)을 결합하고 다시 분리할 수 있는 프로그램이 있습니까?

여러 입력 파일/스트림을 단일 스트림(가상 명령 사용 stream-cat)으로 연결하고 해당 스트림을 원격 호스트로 파이프한 후 이 예제와 같이 ssh원격 호스트( )에서 별도의 파일/스트림으로 다시 분리하려고 합니다. stream-sep목적으로만:

stream-cat <( zfs send tank/vm@snapshot ) somefile.txt | ssh user@host "stream-sep >( zfs receive tank/vm@snapshot ) somefile.txt"

설명 예시: zfs send크기를 미리 알 수 없는 큰 문자열의 데이터를 출력합니다(그래서 tar처리할 수 없습니다). 이 데이터 스트림은 일반 파일의 내용과 연결됩니다 somefile.txt. 결과 스트림은 파이프로 연결되어 ssh다시 분리됩니다. 첫 번째 스트림은 로 파이프되고 zfs receive두 번째 스트림은 일반 파일에 기록됩니다.

이러한 프로그램은 검색할 수 없는 스트림을 청크로 읽고 항상 청크 크기를 쓴 다음 스트림 끝에 도달할 때까지 데이터를 기록하여 구현하기 쉬워야 합니다. 오버헤드는 최소화됩니다.

그런 프로그램이 이미 존재하나요?

답변1

당신이 설명하는 것은재사용; 무언가 필요해규약(즉, 데이터 처리 방법에 대한 공식적인 사양)

이를 달성하는 방법에는 여러 가지가 있습니다. 예를 들어, 컴퓨터가 동일한 서버에서도 HTTP를 통해 여러 파일을 동시에 완벽하게 다운로드할 수 있다는 것을 알 수 있습니다. 이 기능은 서로 다른 스트림을 전송하고 수신 측에서 "분리"할 수 있는 전송 프로토콜 역할을 하는 TCP에 의해 처음 도입되었습니다.

따라서 TCP는 이미 이 기능을 제공하므로 두 개의 동시 SSH 연결을 시작하고 사용하기만 하면 됩니다!

zfs send | zstd -10 | ssh user@host 'zstd -d | zfs receive tank/vm@snapshot' &
# ^         ^    ^     ^             ^     ^   ^                             ^
# |         |    |     |             |     |   |                             |
# |         |    |     |             |     |   |     Tell your own shell to run
# |         |    |     |             |     |   |     this in the background and
# |         |    |     |             |     |   |     not block
# |         |    |     |             |     |   |                         
# |         |    |     |             |     |   |                            
# |         |    |     |             |     |   \---- Program to receive in the end
# |         |    |     |             |     |
# |         |    |     |             \-----+-------- use zstd to decompress
# |         |    |     |                             received data
# |         |    |     |            
# |         |    |     |
# |         |    |     \---------------------------- our first ssh invocaton
# |         |    |
# |         \----+---------------------------------- use zstd to compress at medium
# |                                                  high compression level (10)
# |
# \------------------------------------------------- the first program whose output
#                                                    we send

cat somefile.txt | ssh user@host 'cat > somefile.txt'
#                                                    Second SSH connection

물론 약간 덜 우아한 것 대신 cat somefile.txt | ssh … > somefile.txt직접 사용할 수도 있습니다 scp somefile.txt user@host:somefile.txt(내부적으로 SSH를 사용하지만 셸 연결을 수행하는 대신 SSH에 내장된 SCP 계층을 사용하여 파일을 복사함).

파일에 다음을 추가하면 두 번째 연결을 더 빠르게 만들 수 있습니다 ~/.ssh/config.

ControlMaster auto
ControlPath /tmp/.ssh-socket-%h_%p_%r

이는 SSH가 SSH 세션을 재사용하여 여러 암호화된 스트림을 동시에 보내도록 지시합니다(이는 scp및 의 모든 조합에서도 작동함).ssh

답변2

stream-cat대략적인 구현은 다음 stream-sep과 같이 쉽게 작성할 수 있습니다 perl.

stream-cat() {
  perl -ne 'BEGIN{$/ = \0x7fff}
            print pack("n", $c|length()<<1), $_;
            $c = !eof' -- "$@"
}
stream-sep() {
  perl -e 'while($/ = \2, $_ = <STDIN>) {
             $n = unpack "n";
             open OUT, shift@ARGV unless $n & 1;
             if ($n>>=1) {$/ = \$n; $_ = <STDIN>; print OUT}
           }' -- "$@"
}

또는 함수 #! /bin/sh -대신 스크립트와 동일합니다 .sh

(오류 처리는 독자 여러분의 연습 문제로 남겨두었습니다 :-).

stream-cat네트워크 인코딩(빅 엔디안) 짧은 형식이 앞에 붙은 최대 32767바이트의 레코드를 보냅니다. n이 중 가장 낮은 비트는 새 스트림(0)의 시작인지 연속인지를 나타내고 나머지 비트는 크기.

그런 다음 예를 들면 다음과 같습니다.

$ cat a
test
$ stream-cat 'seq 10|' a | stream-sep '|wc -l' '>b'
10
$ cat b
test

귀하의 경우에는 다음과 같습니다.

stream-cat 'zfs send tank/vm@snapshot|' somefile.txt |
  ssh user@host 'stream-sep "|zfs receive tank/vm@snapshot" ">somefile.txt"'

드문 경우지만 안전하지 않은 형식 open(여기서는 <>as 및 as 로도 사용됨 -n)이 실제로 유용하여 파일을 읽기 전용 또는 쓰기 전용 모드로 열거나 <file명령 으로 파이프하거나 명령에서 파이프할 수 있습니다.>file|cmdcmd|

이것을 사용하는 것이 |cmd/ 당신의 것보다 낫습니다 / cmd|한 번에 하나만 열려 있으므로 문제 없이 수천 개의 별도 스트림을 보낼 수 있습니다.<(cmd)>(cmd)

관련 정보