ssh - 복잡한 원격 명령 실행

ssh - 복잡한 원격 명령 실행

나는 다음을하고 싶다껍데기명령을외딴기계:

/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out

retail이 명령은 기본적으로 약간의 설탕이 추가된 일반 Linux 인 바이너리를 사용합니다 . tail자세한 내용은 다음을 확인하세요.이것github 저장소.

쉘에 위의 명령을 입력하면원격 컴퓨터에서그것은 내가 원하는 것을 그 자체로 수행하므로 작성된 명령은 기능적 관점에서 정확합니다. 그것은 내가 원하는 것을 합니다.

문제는 내가 원하는 것이다.구현하다이 명령은 스크립트에서내 노트북에원격 시스템을 트리거합니다.

이게 뭐야?나는 노력했다, 그러나 모든 명령은 원하는 출력을 인쇄하지 않고 대신로그 줄을 인쇄하지 않음완전히:

ssh [email protected] /bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out

[그런 다음 탈출을 시도 하거나 대신 ]사용하려고 시도했지만 아마도 모든 조합을 사용했지만 모든 것'"쓸모 없는.

이것원하는 출력예: Normal 처럼 동작하며 tail새 줄이 문자열의 지정된 줄과 일치하면 종료됩니다.마찬가지로 원격 컴퓨터에서 실행하면 다음과 같이 작동합니다.

나는 스스로에게 물었습니다: 아마도 retailSSH를 통해 실행될 수 없을까요? 나는 일반 유닉스를 사용해 tail보았고효과가있다SSH를 통해. 작가님이 retail그러시는데POSIX 호환tail그의 시스템을 그것으로 대체 할 수 있다 . 그래서 이것도 그런 것 같아요.괜찮아요바이너리 파일 자체.

따라서 질문은 다음과 같습니다. ssh명령을 올바르게 가져오도록 명령의 매개변수 형식을 어떻게 지정합니까?


댓글에 대한 응답자켄551:

다음을 의미하는 경우:

ssh [email protected] '/bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out'

그리고 네, 시도해 봤습니다. 인쇄도 됩니다로그 라인 없음그리고 입력 프롬프트로 돌아가지 않습니다.


정답에 대한 반응제럴드 필레:

안타깝게도같은 행동. 로그를 인쇄하지 않으며 입력 프롬프트를 반환하지 않습니다. 완전성을 위해 다음을 시도했습니다.

ssh [email protected] /bin/retail -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

정답에 대한 반응패트릭:

불행하게도 부정적이기도 합니다. 완전성을 기하기 위해 제안된 두 가지 솔루션을 모두 시도했습니다. 여기첫 번째:

CMD="$(printf "%q " /bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
ssh [email protected] "$CMD"

결과:로그를 인쇄하지 않으며 입력 프롬프트를 반환하지 않습니다.

게다가두번째:

ssh -T [email protected] <<'EOF'
/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF

결과:의사 터미널을 출력하지만로그가 아님그리고 실제로아니요돌아가다입력 프롬프트:

 Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux my-remote-server 4.1.15-1-lts #1 SMP Tue Dec 15 20:54:13 CET 2015 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

내가 이래로시험을 마친이제 시도해야 할 몇 가지 솔루션이 있습니다.sh 스크립트 호출, 다음 retail명령이 포함되어 있습니다.제럴드 필레제안. 나는 아직도 갖고 싶다좋은 한 줄가능하다면(해당 줄을 포함하는 스크립트를 작성할 필요가 없습니다).


응답아처마르답변:

원래 명령을 사용하여 지정하고 -t여기에 a를 추가했는데 결과는 다음과 같습니다.

ssh -t [email protected] /bin/retail -f -u "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out

그리고효율적인. Archemar 당신은 당신의 글을 작성해야합니다답변으로 댓글 달기그래서 확인해 볼 수 있어요.

답변1

때때로 명령이 터미널을 처리하는데, 이는 문제가 아니므로 터미널을 할당 $PATH할 수도 있습니다 .sshtty

~에 따르면man ssh

-t 의사 터미널 할당을 강제합니다. 이는 원격 컴퓨터에서 임의의 화면 기반 프로그램을 실행하는 데 사용할 수 있으며, 이는 예를 들어 메뉴 서비스를 구현할 때 유용합니다. 여러 -t 옵션은 ssh에 로컬 tty가 없더라도 tty 할당을 강제합니다.

그냥 사용

ssh -t sshuser@host ...

답변2

Jaken551의 제안은 실용적인 솔루션에 가깝지만 추가 수준의 중첩된 참조로 인해 약간 다릅니다. 먼저 무슨 일이 일어나고 있는지 살펴 보겠습니다.

echo나의 일반적인 기술은 명령 앞에 a를 붙이는 것입니다(완벽하지는 않지만 일반적으로 충분합니다).

# Your original command which you say works locally
$ echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

# The command though ssh
$ ssh example.com echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out
INFORMATION [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler [ajp-nio-8009] /opt/tomcat/logs/catalina.out

# The command through ssh with the quotes
$ ssh example.com 'echo "INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]" /opt/tomcat/logs/catalina.out'
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \["ajp-nio-8009"\] /opt/tomcat/logs/catalina.out

따라서 출력의 차이에 유의하시기 바랍니다. 이 두 ssh버전에서는 이스케이프가 다릅니다.

첫 번째 예에서 일어나는 일은 ssh첫 번째 수준 참조가 로컬 셸에 의해 제거되고 ssh여러 인수( echo, INFORMATION \[main\] ...)를 받은 다음 함께 연결되어 단일 인수를 형성하고 echo INFORMATION \[main\] ...로컬 셸의 셸에서 평가되는 것입니다. 원격 끝은 sh -c 'echo INFORMATION \[main\] ...'.

두 번째 ssh예에서는 첫 번째 수준 참조가 로컬 셸에 의해 다시 제거되므로 ssh가 이를 수신 echo "INFORMATION \[main\] ..."한 다음 원격 측에서 평가합니다 sh -c 'echo "INFORMATION \[main\] ..."'. 그래서 조금 더 나아졌지만 여전히 따옴표와 이스케이프를 제거하여 2개의 쉘 레이어를 처리해야 합니다.

 

이 문제를 해결하는 방법에는 두 가지가 있습니다. 첫 번째 방법은 STDIN에서 명령을 전달하는 것입니다. 그러면 명령이 실제로 실행될 때 셸에서 한 번만 처리됩니다.

ssh -T example.com <<'EOF'
echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

그러나 이는 원격 명령이 TTY 또는 STDIN에 액세스할 수 없음을 의미하므로 명령에 STDIN이 필요한 경우 작동하지 않습니다.

두 번째 방법은 쉘이 추가 견적 수준을 추가하도록 하는 것입니다.

$ CMD="$(printf "%q " echo 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
$ ssh example.com "$CMD"
INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out

(중개자가 필요하지 않습니다 $CMD. 인라인으로 수행할 수 있습니다 ssh ... "$(printf "%q " ...)". 가독성을 위해 별도로 수행했습니다.)

 

핵심요약: 다음 방법 중 하나가 적합할 수 있습니다.

ssh -T [email protected] <<'EOF'
/bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out
EOF

CMD="$(printf "%q " /bin/retail -f -u 'INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]' /opt/tomcat/logs/catalina.out)"
ssh [email protected] "$CMD"

답변3

원하는 작업을 수행하는 다른 시스템에서 스크립트를 만든 다음 매개 변수 없이 해당 스크립트를 호출하면 작업이 훨씬 쉬워집니다. 또 다른 방법은 수신한 인수를 표시하는 스크립트를 반대쪽에서 만드는 것입니다(예: echo_args.sh).

#!/bin/ksh

echo "$0 $@"
ARG=1
while [ $# -gt 0 ]
do
  echo "$ARG: $1"
  shift
  (( ARG++ ))
done

그런 다음 다음으로 전화할 수 있습니다.

ssh [email protected] bin/echo_args.sh  -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

당신은 다음을 얻습니다:

bin/echo_args.sh -f -u INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\] /opt/tomcat/logs/catalina.out
1: -f
2: -u
3: INFORMATION \[main\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \[\"ajp-nio-8009\"\]
4: /opt/tomcat/logs/catalina.out

이는 매개변수가 반대쪽 끝에 올바르게 도달했음을 나타냅니다. 이제 echo_args.sh를 소매 프로그램으로 바꾸면 됩니다.

ssh [email protected] /bin/retail -f -u \'INFORMATION \\[main\\] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler \\[\\\"ajp-nio-8009\\\"\\]\' /opt/tomcat/logs/catalina.out

관련 정보