배쉬 : 대화식 원격 프롬프트


16

원격 서버에 연결하고 일부 패키지가 설치되어 있는지 확인하는 스크립트가 있습니다.

ssh root@server 'bash -s' < myscript.sh

myscript.sh :

OUT=`rpm -qa | grep ntpdate`
if [ "$OUT" != "" ] ; then
    echo "ntpdate already installed"
else
    yum install $1
fi

이 예제는 단순화 될 수 있습니다. 다음은 myscript2.sh동일한 문제가 있습니다.

read -p "Package is not installed. Do you want to install it (y/n)?" choise

내 문제는 bash가 대화 형으로 내 대답을 읽을 수 없다는 것입니다.

사용자에게 프롬프트하지 않고 로컬 스크립트를 원격으로 실행할 수있는 방법이 있습니까?


정교하게 할 수 있습니까? 무엇을 원하는지 확실하지 않습니까? 더 많은 코드가 도움이 될 것입니다.
slm

1
참고로, 이것이 작동하지 않는 이유는 STDIN을 통해 스크립트를 전달하기 때문입니다. 따라서 bash가 STDIN에서 읽 히면 스크립트를 얻습니다 (또는 전체 스크립트를 이미 읽었으며 남은 것이 없기 때문에 아무것도 아닙니다).
패트릭

1
이것에 관한 유용한 자원 : backreference.org/2011/08/10/…
slm

답변:


22

다음과 같이 해보십시오 :

$ ssh -t yourserver "$(<your_script)"

-t힘 청각 장애 할당, $(<your_script)전체 파일을 읽고,이 경우 하나 개의 인수로 콘텐츠를 전달 ssh원격 사용자의 쉘에 의해 실행됩니다.

스크립트에 매개 변수가 필요한 경우 스크립트 뒤에 매개 변수를 전달하십시오.

$ ssh -t yourserver "$(<your_script)" arg1 arg2 ...

그것이 보편적인지 아닌지는 확실하지 않습니다.


3
바로 내가 찾던 것입니다, 감사합니다!
Anthony Ananich

좋은 해결책이지만에 your script사용 된 구문의 장점을 유지하면서 인수를 전달하는 방법이 있습니까? 를 사용하면 ssh -t yourserver "$(<your_script --some_arg)"결과가됩니다 bash: --some_arg: command not found.
sampablokuper

1
@sampablokuper : 시도ssh ... $(<script) script_arg1 script_arg2 ...
Mat

@ 매트, 고마워, WFM :) 아마도 대답의 본문에 추가 할 수 있습니까?
sampablokuper

3

문제는 ssh원격 시스템에서 비 대화식 로그인 을 시작하는 것입니다. 명백한 쉬운 해결책은 스크립트를 원격 서버에 복사하여 거기서 실행하는 것입니다.

scp myscript.sh root@server:/tmp && ssh root@server /tmp/myscript.sh

어떤 이유로 든 복사가 옵션이 아닌 경우 스크립트를 수정하여 먼저 연결하고 $1설치되어 있는지 확인한 다음 필요에 따라 다시 연결하고 설치하십시오.

OUT=$(ssh root@server rpm -qa | grep "$1");
if [ "$OUT" != "" ] ; then
    echo "$1 already installed"
else
   read -p "Package $1 is not installed. Do you want to install it (y/n)?" choice
   if [ "$choice" -eq "y" ]; then
       ssh root@server yum install "$1"
   fi
fi

그것이 내가 두려워했던 것입니다. ssh에 연결하는 것이 가장 긴 작업이며 피하려고했습니다.
Anthony Ananich

@AnthonyAnanich 마스터 연결설정 하여 연결 설정 시간을 절약 할 수 있습니다 .
Gilles 'SO- 악의

@ Giles 나는 그것을 제안하려고 생각했지만 내 제안으로는 작동하지 않을 것이라고 생각했습니다. 첫 번째 ssh 연결이 마스터 역할을하는 경우 $OUT=$(ssh root@server rpm -qa | grep "$1");종료 후 닫히고 두 번째 연결은 첫 번째 연결 시간만큼 걸립니다. 내가 잘못?
terdon

1
@terdon 실행 같은 ssh -M foo.example.com sleep 99999999또는 ssh -M foo.example.com read <somefifo마스터로와 (명시 적 죽일 kill또는 echo done >somefifo작업을 완료 할 때).
Gilles 'SO- 악마 그만해

0

여기 좋은 설명이 있습니다.

그래서 나는 스크립트를

hostname
echo -n "Make your choice :"
read choice
echo "You typed " ${choice}
echo done

그리고 이것은 작동하지 않았습니다.

그래서 ssh의 로컬 리디렉션을 피하기 위해 스크립트를 원격으로 옮겼습니다. (내 명령은 f 라는 파일에 있습니다. )

cat f | ssh user@remotehost.com 'cat >remf'
ssh user@remotehost bash remf

이것은 효과가 있었다. 출력은 다음과 같습니다.

christian@clafujiu:~/tmp$ ssh localhost bash tmp/f
christian@localhost's password: 
Linux clafujiu 2.6.32-52-generic #114-Ubuntu SMP Wed Sep 11 19:00:15 UTC 2013 i686 GNU/Linux
Sun Nov 10 14:58:56 GMT 2013
Make your choice :abc
You typed  abc
done

@terdon은 원래의 강렬이 로컬 스크립트를 원격으로 실행하는 것이라고 언급 했으므로 원격 사본을 자동화 할 수 있습니다.

REMID=`cat f |ssh user@remotehost 'cat > remf_$$; echo $$'` ;ssh root@redtoadservices.com "bash remf_${REMID} ; rm -v remf_${REMID}"

2
어떻게 "작동"했습니까? bash -s < script.shOP처럼 이 스크립트를 실행 했습니까 ? 답변에 연결하는 대신 설명을 설명에 포함시킬 수 있습니까?
terdon

죄송합니다. 중요한 것을 추가하는 것을 잊었습니다. 또한 로컬 리디렉션을 피하기 위해 스크립트를 원격으로 복사했습니다. 나는 이것을 명확하게하기 위해 내 대답에 추가 할 것입니다.
X Tian

1
스크립트를 원격으로 복사하면 문제가 해결됩니다. OP의 문제는 원격으로 실행 되는 로컬 스크립트에 대화식 입력을 제공하려고한다는 것 입니다. 물론 그것은 당신을 통해 복사됩니다. OP는 원격 서버, 아마도 많은 원격 서버에 연결할 때이 스크립트를 실행하려고합니다. 자동화하지 않으면 그것을 복사하는 것이 실용적이지 않습니다.
terdon

0

과거 에이 문제에 대한 솔루션을 여러 번 검색했지만 완전히 만족스러운 솔루션을 찾지 못했습니다. ssh에 파이핑하면 대화 형 작업이 느슨해집니다. 두 개의 연결 (scp / ssh)이 느리고 임시 파일이 남아있을 수 있습니다. 그리고 명령 행의 전체 스크립트는 종종 지옥에서 빠져 나옵니다.

최근에 커맨드 라인 버퍼 크기가 일반적으로 매우 크다는 것을 알게되었습니다 ( 'getconf ARG_MAX> 2MB). 그리고 이것이 어떻게 이것을 사용하고 탈출 문제를 완화시킬 수 있는지 생각하게했습니다.

결과는 다음과 같습니다.

ssh -t <host> /bin/bash "<(echo "$(cat my_script | base64 | tr -d '\n')" | base64 --decode)" <arg1> ...

또는 here 문서와 고양이를 사용하십시오.

ssh -t <host> /bin/bash $'<(cat<<_ | base64 --decode\n'$(cat my_script | base64)$'\n_\n)' <arg1> ...

이 아이디어를 확장하여 sshx인수가 ssh를 통해 로컬 입력 파일이 될 수있는 BASH뿐만 아니라 임의의 스크립트를 실행할 수 있는 완전히 작동하는 BASH 예제 스크립트를 생성했습니다 . 여기를 참조 하십시오 .


흥미롭지 만 어떻게 그리고 / 또는 언제 매트의 대답 보다 낫 습니까?
Scott

1
Mat의 대답 은 좋은 첫 번째 패스 (자주 사용하는)이지만 "이스케이프 해야하는 문자 와 같은 임의의 내용 스크립트를 처리 할 수 ​​없습니다 . 또한 BASH 스크립트로 제한됩니다. 내 솔루션은 설치된 스크립팅 언어의 스크립트 내용에 대한 일반적인 경우입니다. 또한 sshx 에서 인수 파일을 직렬화하는 방법을 추가로 보여줍니다.
SourceSimian

(1) Mat의 답변이 실패하고 작동하는 스크립트의 MCVE를 게시 할 수 있습니까? (2) “echo $ (stuff)”또는“echo`stuff`”의 문제점을 참조하십시오.  귀하의 echo "$(cat my_script | base64)" | base64 --decode외모는 (-ish) cat my_script | base64 | base64 --decode와 같으며 no-op와 비슷합니다.
Scott

안녕하세요 @Scott. (1) : 스크립트를 고려하십시오 echo "ARG1=$1, USER=$USER, END". a) $ ssh host "$(<my_bash)" foo-> ARG1=, USER=user, END foo. b) $ ssh host bash "<(echo $(cat my_bash|base64) | base64 --decode)" foo-> ARG1=foo, USER=user, END. 여기서 (a)는 효과적으로 운영되고 bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'있습니다. 인수가 작동하지 않습니다. (b)가 실행중인 위치 : bash <(echo IyEvY...5EIgo= | base64 --decode) foo. (2) 전송 인코딩으로 base64를 사용했습니다.
SourceSimian 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.