stdin을 통해 여러 파일 전달 (ssh를 통해) 내 장치에만 존재합니다. SSH를

원격 호스트에 프로그램이 있는데 그 실행을 자동화해야합니다. 동일한 컴퓨터에서 해당 프로그램을 실행하는 명령은 다음과 같습니다.

/path/to/program -a file1.txt -b file2.txt

이 경우, file1.txt그리고 file2.txt프로그램 내에서 완전히 다른 일에 사용, 그래서 난 그냥 수 없습니다되어 cat그들을 함께. 그러나 필자의 경우 프로그램에 전달하려는 file1.txtfile2.txt프로그램은 프로그램을 실행 해야하는 호스트가 아닌 내 장치에만 존재합니다. SSH를 통해 적어도 하나의 파일을 전달할 수 있다는 것을 알고 있습니다 stdin.

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt

그러나 호스트에 파일을 저장할 수 없으므로 파일을 가져올 수있는 방법이 필요합니다 file2.txt. 환경 변수를 남용하고 창의적으로 사용 cat하고 sed함께 사용하여 가능할 수 있다고 생각 하지만 도구를 사용하여이를 달성하는 방법을 충분히 이해할 수는 없습니다. 어떻게 할 수 있습니까?



답변

프로그램에 인수로 제공된 파일이 텍스트 파일이고 해당 내용을 제어 할 수있는 경우 (파일 내부에서 발생하지 않는 행을 알고 있음) 여기에서 여러 문서를 사용할 수 있습니다.

{
    echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
    cat file1
    echo EOT
    cat file2
    echo EOT
    cat file3
    echo EOT
} | ssh user@host sh

다음 cat은 파일 이름을 인수로 사용하는 샘플 명령입니다. 대신 할 수 있습니다 :

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'

EOT파일에서 각각 발생하지 않는 것으로 바꿉니다 .


답변

아마도 정확히 당신이 원하는 것은 아니지만 … 아마도 ssh에 의해 열린 파이프를 통해 tarball을 보내는 것을 고려할 수 있습니까?

당신은 말했다 :

호스트에 파일을 저장할 수 없습니다.

쓰기 가능한 홈 디렉토리 나 파일을 장기간 저장할 수있는 다른 편리한 위치가 없을 수도 있지만 임시 tmpfs로만 사용할 수 있는 쓰기 가능한 위치가 없을 가능성이 높습니다. 특정 연결.

많은 프로그램들 (그리고 libc 루틴들조차도)은 쓰기 가능을 요구 /tmp하므로, 아마도 당신이 사용할 수있을 것입니다.

그런 다음 tarball을 임시 디렉토리에 압축 해제하고 프로그램을 실행하고 ssh 연결을 통해 정리하는 스크립트를 사용할 수 있습니다.

다음과 같은 것 :

$ tar cf - file1.txt file2.txt |
  ssh host.name '
      set -e
      tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
      cleanup () { rm -rf "$tmpdir"; }
      trap cleanup EXIT
      cd "$tmpdir"
      tar xf -
      /path/to/program -a file1.txt -b file2.txt
  '

이것은 파일 경로에 대해 약간의주의가 필요할 수 있으며 고려해야 할 몇 가지 경우가 있지만 일반적인 접근 방식이 효과적입니다.

쓰기 가능한 디렉토리가 없으면 programtarball을 단일 입력으로 가져 와서 내용을 메모리에 압축 해제 하도록 수정하는 것이 가능 합니다. 예를 들어 programPython 스크립트 인 경우 내장 tarfile모듈 을 사용하면 쉽게 이와 같은 작업을 수행 할 수 있습니다.


답변

TCP 리스너 (더 높은 포트 일 수 있음)를 설정할 수 있으면 두 번째 SSH 세션을 사용하여을 사용하여 두 번째 입력 소스를 설정할 수 있습니다 nc.

예:

서버 ( ~/script.bash) 에이 스크립트가 있습니다 .

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'

로컬로이 두 파일이 있습니다.

$ cat a
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb

이제 두 번째 소스를 시작하십시오 ( $serv서버).

ssh "$serv" nc -l -p 2222 -q1 <b &

그리고 명령을 적절하게 실행하십시오 :

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b

답변

그것은 년에 설립 된 의견/tmp 때문에 단순히 사전 파일 중 하나를 복사, 쓰기 가능합니다 :

scp -p file2.txt host.name:/tmp/
ssh host.name "/path/to/program -a /dev/stdin -b /tmp/file2.txt && rm /tmp/file2.txt" < file1.txt

이것은 또한 성공적인 실행합니다 (변경 후 복사 된 파일 정리 &&A와 ;관계없이 성공을 제거하려면,하지만 당신은 종료 값을 잃게됩니다주의를).


그것이 수용 할 수 없다면, /path/to/program다음과 같은 단일 입력 스트림에서 두 파일을 분리 할 수있는 땜장이 또는 래퍼를 제안 합니다.

awk 'FNR == 1 && NR > 1 { printf "%c%c%c", 28, 28, 28 } 1' file1.txt file2.txt \
  | ssh host.name /path/to/tweaked_program

이것은 ASCII 정보 구분자 4 (파일 구분자, FS)를 사용하며이 문자열이 우연히 포함 된 이진 파일의 가능성을 최소화하기 위해 3 배가되었습니다. 귀하는 tweaked_program다음 구분 주어진 입력을 분할 한 후 변수로 두 저장된 파일에서 작동합니다.

물론, tarball을 다루기 위해 라이브러리가있는 언어를 사용하는 경우,보다 안전하고 깔끔한 접근 방식은 tar다음과 같은 코드 로 파이프하는 것입니다 ssh.

tar -zpc file1.txt file2.txt |ssh host.name /path/to/tweaked_program

그리고 tweaked_program압축을 풀고 아카이브를 열고 각 파일을 다른 변수에 저장 한 다음 원본을 실행하십시오.program 의 논리 .


답변

당신이 이상의 포트를 전달하도록 허용하는 경우 ssh, 당신은에 액세스 할 수있는 wget원격 시스템과에 busybox로컬 컴퓨터에, 당신은 뭔가를 할 수 있습니다 :

mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file

busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
        cat <(wget -q -O- http://localhost:10080/1st_file) \
            <(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!

(사용 cat 두 개의 파일 인수를 취하는 예제 프로그램으로 ).

-Rhttp를 수행하는 대신 포트를 전달하는 기능 만 필요합니다 . 예를 들어 다른 방법을 사용할 수 있습니다. 및 옵션을 netcat지원하는 경우 :-d-N

nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
        cat <(nc -d localhost 10001) <(nc -d localhost 10002)

교체 방법이있을 수 있습니다 <(...)원격 시스템의 로그인 쉘이 ksh 또는 bash와 다른 경우 프로세스 대체 .

전체적으로 이것은 너무 크지 않습니다. 제공하지 않은 정확한 시스템 / 쉘 / 구성 / 권한에 대한 더 나은 지식은 더 똑똑한 솔루션을 제공 할 수 있습니다.


답변

업데이트 : 이것은 실제로 작동하지 않습니다 .ssh는 stdin 및 stdout / stderr의 의미에 대해 매우 정립되어 있으며 실제로 stderr을 읽을 수 없습니다. 작동하지 않으므로 며칠 안에이 답변을 삭제하겠습니다. 매우 흥미로운 토론에 감사드립니다 !!!


불행하게도 거기에 있기 때문에, 직접이 작업을 수행 할 수있는 좋은 방법이 아니다 ssh클라이언트 만 (세 개의 파일 디스크립터를 전달합니다는 stdin, stdoutstderr ) 서버에 그것은이 특정 사용 사례에 대한 도움이 될 것입니다 추가 파일 기술자를 (전달하는 조항이없는 .)

또한 SSH 프로토콜에는 추가 파일 디스크립터를 전달하는 조항이 있으며 ssh 클라이언트 해당 기능을 사용하는 방법을 구현하지 않습니다. 이론적으로 패치를 사용하여 클라이언트를 확장하면이 기능을 노출 할 수 있습니다.

찾고있는 것을 성취하는 해킹 방법 중 하나 는 파일 설명자 2 ( stderr파일 설명자)를 사용하여 두 번째 파일을 전달하는 것입니다. 다음과 같은 것 :

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/stderr \
      <file1.txt 2<file2.txt

이것은 작동해야 program하며 stderr에 쓰려고 하면 문제가 발생할 수 있습니다 . 프로그램을 실행하기 전에 원격 끝에서 파일 디스크립터를 다시 저글링하여이 문제를 해결할 수 있습니다. file2.txt파일 디스크립터 3으로 이동 하고 stderr을 다시 열어 stdout을 미러링 할 수 있습니다 .

$ ssh remote.name \
      /path/to/program -a /dev/stdin -b /dev/fd/3 \
      '3<&2' '2>&1' \
      <file1.txt 2<file2.txt