컬의 출력을 ssh 명령으로 파이프하거나 리디렉션합니다.

컬의 출력을 ssh 명령으로 파이프하거나 리디렉션합니다.

나는 이것이 불가능하다고 확신하지만 과거에는 틀렸습니다.

기본적으로 내가 원하는 것은 컬 명령의 JSON 출력을 가져와서 jq로 파이프하여 깔끔하게 유지하는 것입니다. 좋은 결과. 하지만 OSX에는 이 기능이 없으므로 Brew나 다른 방법을 통해 설치해야 합니다. 나에게는 문제가 되지 않습니다. 그러나 기업 환경에서는 타사 애플리케이션을 설치하는 것이 눈살을 찌푸리게 합니다. 그러나 다수의 Linux 서버에는 jq가 설치되어 있습니다.

jq를 실행하기 위해 로컬 출력을 ssh로 파이프할 수 있습니까?

curl https://whatever.site/json | ssh linuxHost "jq '.'" > output.json

많은 수의 Linux 서버에는 외부 액세스 권한이 없으므로 그곳에서 컬 명령을 실행하면 작동하지 않는다는 점에 유의하는 것이 중요합니다. 예, scp를 만들 수 있지만 더 많은 단계가 있습니다.

답변1

당신이 하고 싶은 게 전부라면아름다운 인쇄JSON 문서(고급 필터링, 집계 또는 기타 항목 제외)를 사용하면 macOS 기본 시스템 유틸리티의 더 간단한 유틸리티인 json_pp( )를 사용할 수 있습니다 . /usr/bin/json_ppjson_pp유틸리티는 Perl 모듈용 명령줄 래퍼입니다 JSON::PP.

$ echo '{ "hello": "world!" }' | json_pp
{
   "hello" : "world!"
}

man json_pp사용자 정의 출력 형식( -json_opt옵션) 에 대한 설명은 참고자료를 참조하세요 .

예:

$ echo '{ "hello": "world!" }' | json_pp -json_opt pretty,indent_length=2,space_before=0
{
  "hello": "world!"
}

답변2

예, ssh명령을 실행 하는 경우 모드 대신에 ssh가상 터미널의 원격 시스템에서 사용자 로그인 셸을 실행하는 대신 세 가지 다른 파이프라인에 연결된 stdin, stdout 및 stderr을 사용하여 지정된 명령을 실행합니다.rshrloginsshd

이러한 파이프의 내용은 암호화된 터널을 통해 전송되며 프로세스의 stdin, stdout 및 stderr에서 읽거나 씁니다 ssh.

그래서:

local-cmd | ssh 'remote-cmd' > file
  • sshstdin은 local-cmd기록되는 파이프를 읽는 것입니다.
  • ssh표준 출력은 file쓰기 전용 모드로 열립니다.
  • ssh터미널에서 실행하는 경우 stderr은 아마도 터미널 장치일 것입니다.

그리고

  • 표준 입력의 판독값은 ssh암호화된 채널을 통해 전송되어 remote-cmd입력으로 파이프됩니다.
  • 표준 출력의 파이프에 기록된 내용은 remote-cmd암호화된 채널을 통해 전송되고 sshd(해당 파이프의 다른 쪽 끝에서 읽음) ssh수신 시 표준 출력에 기록됩니다. 즉, 파일에 기록됩니다.
  • remote-cmd별도의 파이프에서 stderr과 동일합니다.

lsof를 사용하여 이를 관찰할 수 있습니다.

$ sleep 3 | ((sleep 1; lsof -wc ssh -ad 0-99 +E >&2) <&- & ssh [email protected] 'lsof -wp "$$" -ad 0-2 +E; sleep 2') > file
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
screen   7561 chazelas    9u   CHR    5,2      0t0      89 /dev/ptmx ->/dev/pts/5 63562,zsh,0u 63562,zsh,1u 63562,zsh,2u 63562,zsh,10u 63608,sleep,0u 63608,sleep,2u 63609,ssh,2u 63609,ssh,6u 63610,lsof,1u 63610,lsof,2u
sleep   63608 chazelas    1w  FIFO   0,14      0t0  698683 pipe 63609,ssh,0r 63609,ssh,4r
ssh     63609 chazelas    0r  FIFO   0,14      0t0  698683 pipe 63608,sleep,1w 63609,ssh,4r
ssh     63609 chazelas    1u   CHR    1,3      0t0       5 /dev/null
ssh     63609 chazelas    2u   CHR  136,5      0t0       8 /dev/pts/5 7561,screen,9u
ssh     63609 chazelas    3u  IPv4 697921      0t0     TCP localhost:50006->localhost:ssh (ESTABLISHED)
ssh     63609 chazelas    4r  FIFO   0,14      0t0  698683 pipe 63608,sleep,1w 63609,ssh,0r
ssh     63609 chazelas    5w   REG   0,39      540 8488375 /home/chazelas/file
ssh     63609 chazelas    6u   CHR  136,5      0t0       8 /dev/pts/5 7561,screen,9u
~$ cat file
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
sshd    63612 root    5w  FIFO   0,14      0t0 698269 pipe 63692,bash,0r 63695,lsof,0r
sshd    63612 root    7r  FIFO   0,14      0t0 698270 pipe 63692,bash,1w 63695,lsof,1w
sshd    63612 root   10r  FIFO   0,14      0t0 698271 pipe 63692,bash,2w 63695,lsof,2w
bash    63692 root    0r  FIFO   0,14      0t0 698269 pipe 63612,sshd,5w
bash    63692 root    1w  FIFO   0,14      0t0 698270 pipe 63612,sshd,7r
bash    63692 root    2w  FIFO   0,14      0t0 698271 pipe 63612,sshd,10r

sshfds 4와 5(fds 0과 1에서 복사됨)가 각각 절전 모드에서 파이프로 들어오는 것을 볼 수 있으며 file, 원격 측(출력이 lsof나타나는 곳 file)에서 원격의 fds 0, 1, 2 쉘에는 3개의 다른 쉘이 있습니다. 파이프는 모두 sshd.

따라서 이러한 방식으로 실행은 표준 IO의 경우 ssh cmd로컬 실행과 기능적으로 유사 cmd하지만 여전히 주목해야 할 몇 가지 사항이 있습니다.

  • 위에 표시된 대로 cmd원격 시스템의 stdin/stdout/stderr은 ssh클라이언트에서의 목적(예: 이 예에서는 각각 파이프, 일반 파일 및 tty 장치)에 관계없이 모두 파이프입니다. 예를 들어 로 리디렉션하지 않는 경우 출력 이 tty 장치로 이동할 때만 색상이 지정되므로 출력에 색상이 지정되지 않은 것을 file알 수 있습니다 .jqjq
  • ssh원격 호스트에서 읽혔는지 여부 에 관계없이 stdin에서 출력을 소비하고 sshd로 보냅니다. cmd예를 들어 원격 명령이 한 줄만 읽었음에도 불구하고 to의 전체 출력이 전송되었으므로 seq 1000 | (ssh localhost 'IFS= read -r one_line_only'; cat)아무 것도 출력되지 않습니다 (대부분의 이유는 읽히지 않음) 읽을 것이 없습니다.readsshseqsshdreadcat

여기서도 다음을 수행할 수 있습니다.

curl... | ssh 'jq . > remotefile'

원격 출력은 jq원격 파일(원격 사용자의 홈 디렉터리)에 저장됩니다. 또는:

curl... | ssh 'jq . | tee remotefile' > localfile

(또는 단순히 curl | ssh 'jq >&1 > remotefile' > localfile원격 사용자의 로그인 셸이 zsh인 경우) 출력이 jq로컬 및 원격으로 저장됩니다.


적어도 openssh의 경우에는stdin과 stdout이 다른 fd에서 반복됩니다.어떤 것이 사용되고 있으며표준 출력은 다음에 다시 열립니다./dev/null, 그러나 이는 구현 세부 사항이며 실제로는 아무런 차이가 없습니다.

관련 정보