Bash 스크립트에서 Expect를 사용하여 SSH 명령에 비밀번호를 제공하십시오.


131

SSH 비밀번호를 제공하기 위해 Bash 스크립트에서 Expect를 사용하려고합니다. 암호를 제공해도 작동하지만 SSH 세션에서 끝나지 않습니다. 배쉬에게 해협으로 돌아 간다.

내 스크립트 :

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com'
expect "password"
send "$PWD\n"
EOD
echo "you're out"

내 스크립트의 출력 :

spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
usr@$myhost.example.com's password: you're out

SSH 세션이 있고 종료 할 때만 Bash 스크립트로 돌아가고 싶습니다.

내가 예상하기 전에 Bash를 사용하는 이유는 메뉴를 사용해야하기 때문입니다. 연결할 장치 / 장치를 선택할 수 있습니다.

SSH 키를 사용해야한다고 응답하려는 사람들은 기권하십시오.


49
첫 번째 줄을 참조하십시오 : SSH 키를 사용해야한다고 응답하려는 사람들은 기권하십시오
Max

54
첫 줄을 좀 더 친숙하게 편집하겠습니다. "제약 조건으로 인해 SSH 키를 사용할 수 없습니다. 예상대로 작동시키는 방법을 찾아야합니다"와 같은 것을 고려할 수 있습니다. 당신은 당신이 키를 사용하지 않는, 그냥 도움이 될하려고 :) @Ignacio하지 않은 이유를 사람들이 자연스럽게 호기심이있을 것으로 기대한다 제안 제약 아닌 감독으로, 그는 간단하게 확인하고 그것을 당신이 그들을 사용하는 것이.
Tim Post

이 경우 커밋을 사용하려고합니다. 그것은이 매우 강력한 스크립트 언어 columbia.edu/kermit/skermit.html#scripts
f3xy

답변:


86

배쉬와 기대를 혼합하는 것은 원하는 효과를 얻는 좋은 방법이 아닙니다. Expect 만 사용하려고합니다.

#!/usr/bin/expect
eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com

# Use the correct prompt
set prompt ":|#|\\\$"
interact -o -nobuffer -re $prompt return
send "my_password\r"
interact -o -nobuffer -re $prompt return
send "my_command1\r"
interact -o -nobuffer -re $prompt return
send "my_command2\r"
interact

bash의 샘플 솔루션은 다음과 같습니다.

#!/bin/bash
/usr/bin/expect -c 'expect "\n" { eval spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com; interact }'

그러면 Enter인터랙티브 한 세션 을 기다렸다가 잠시 기다립니다 .


1
감사합니다. SSH를 통해 로그인 한 후 명령을 입력하려면 어떻게해야합니까?
Max

이 스크립트는 로그인 한 사용자와 함께 비활성 쉘을 반환해야합니다. 나는 질문을 이해하지 못한다. bash에서 동일한 스크립트를 사용하려면 편집 된 항목을보십시오.
Piotr Król

프롬프트가 표시 될 때 암호를 보내는 것과 같은 방법으로, 일단 로그인하면 시스템 명령을 보내려고합니다.
Max

위에 게시 된 샘플 코드가 추가되었습니다. 물론 이것은 프롬프트 변수를 변경 해야하는 경우 my_commandX가 반환 된 프롬프트를 변경하지 않을 때까지 작동합니다.
Piotr Król

@pietrushnic "expect $ prompt"대신 "interact -o -nobuffer -re $ prompt return"을 사용하는 이유를 조금 설명해 주시겠습니까? 후자는보다 일반적으로 사용되는 것 같습니다.
Richard

53

가장 쉬운 방법은 sshpass 를 사용하는 입니다. 우분투 / 데비안 리포지토리 에서 사용할 수 있으며 Bash와의 통합을 처리 할 필요가 없습니다.

예를 들면 :

sshpass -p<password> ssh <arguments>
sshpass -ptest1324 ssh user@192.168.1.200 ls -l /tmp

위 명령은 Bash 스크립트와 쉽게 통합 할 수 있습니다.

참고 : 보안 관련 사항을man sshpass 완전히 이해 하려면 보안 고려 사항 섹션을 읽으십시오 .


그것이 좋은 해결책인지는 모르겠지만 확실히 많이 단순화합니다. 감사합니다
erikbwork

9
보안 측면에서 매우 위험합니다. 명령 행 인수는 시스템의 다른 프로세스에서 읽을 수 있습니다. 그것들을 덮어 쓸 수 있고, 희망적으로 sshpass그렇게 할 수 있지만, 그럼에도 불구하고 여전히 모든 과정에서 암호를 사용할 수있을 때 암호를 사용할 수 있기 전에 시작하는 기간이 있습니다.
Charles Duffy

1
@CharlesDuffy 물론, 당신은 맞습니다. sshpass보안이 가장 중요하지 않은 로컬 네트워크 환경에서 실행되는 간단한 테스트 스크립트가있는 시나리오에서 사용됩니다. 실제로 man sshpass보안 고려 사항에 대한 전체 섹션을 설명하는 섹션이 있습니다. 이 답변을 추가했습니다. 감사합니다.
dotnix

@ erikb85 일반적으로, 패키지는 당신을 위해 모든 더러운 것들을 수행하지만, 모든 경우에, 이들 스크립트는 그 용도로만 만들어진 것이므로, 자신의 것을 추가하는 것보다 더 좋을 것입니다. 이 의견은 바퀴를 재발 명하지 않는 것에 관한 것입니다. 아직 아무도 다루지 않은 경우에만 어려운 일을 처리하십시오. sshpass는 좋은 기능입니다.
m3nda 2016 년

2
완전성을 기하기 위해 "man sshpass"는 잠재적 인 사용자에게 적절한 보안 경고를 제공하고 "-p"는이를 사용하는 가장 안전한 방법이며 환경 변수를 통해 비밀번호를 가져 오는 "-e"옵션을 제공한다고 언급합니다. 적어도 명령 줄에서 유지됩니다.
Ron Burk

22

EOD 바로 앞에 'interact'Expect 명령을 추가하십시오.

#!/bin/bash

read -s PWD

/usr/bin/expect <<EOD
spawn ssh -oStrictHostKeyChecking=no -oCheckHostIP=no usr@$myhost.example.com
expect "password"
send "$PWD\n"
interact
EOD
echo "you're out"

로그 아웃 할 때까지 원격 시스템과 상호 작용할 수 있어야합니다. 그런 다음 Bash로 돌아갑니다.


들어갔다가 바로 나옵니다. "나갔습니다"가 인쇄됩니다.
Emmanuel

8
나는 "interact"와 "EOD"를 "expect eof"로 바꾸었고 그것은 나를 위해 일했다. 이것은 Mac에 있습니다.
Emmanuel

2
이 페이지의 답변 중 어느 것도 저에게 효과적이지 않았지만 @ Emmanuel의 제안에 expect eof따르면 문제가 해결되었습니다.
moertel

를 제거 '에서 usr@$myhost.example.com'그것은 작동합니다. 그리고 아마 당신은 교체해야 \n와 함께 \r,하지만 YMMV
티노

20

몇 달 동안 질문에 대한 답을 찾은 후에 마침내 간단한 스크립트 작성이라는 최상의 해결책을 찾았습니다.

#!/usr/bin/expect

set timeout 20

set cmd [lrange $argv 1 end]
set password [lindex $argv 0]

eval spawn $cmd
expect "Password:"
send "$password\r";
interact

에 넣으면 /usr/bin/exp다음을 사용할 수 있습니다.

  • exp <password> ssh <anything>
  • exp <password> scp <anysrc> <anydst>

끝난!


expect "assword:"당신은 의미 expect "password:"했습니까?
사용자

1
@user는 "assword"모두 일치 Password하고 password.
Ferdinand.kraft

8

또한 사용하십시오

send -- "$PWD\r"

대신 대시 (-)로 시작하는 비밀번호는 실패합니다.

위의 명령은 대시로 시작하는 문자열을 send 명령의 옵션으로 해석하지 않습니다.


8

간단한 Expect 스크립트 :

파일 Remotelogin.exp

    #!/usr/bin/expect
    set user [lindex $argv 1]
    set ip [lindex $argv 0]
    set password [lindex $argv 2]
    spawn ssh $user@$ip
    expect "password"
    send "$password\r"
    interact

예:

./Remotelogin.exp <ip> <user name> <password>

7

헬퍼 도구를 사용하십시오 fd0ssh(ppt가 아닌 hxtools에서). ssh프로그램 에서 특정 프롬프트를 기대하지 않아도 작동 합니다.


대단해! (최소한 우분투 서버에서) 실행하기는 약간 어렵지만 매끄럽게 작동합니다! 우리가 만든 구성 : echo "yoursshpass" | fd0ssh ssh -c -L$port:$ip:$remote_port user@yourserver.com & 감사합니다!
JP Illanes

1
명령 줄에서 암호를 전달하는 것보다 훨씬 안전합니다 sshpass.
Charles Duffy

5

Bash 스크립트에서 작은 Expect 스크립트 를 사용하는 것이 유용한 다른 방법 은 다음과 같습니다.

...
Bash script start
Bash commands
...
expect - <<EOF
spawn your-command-here
expect "some-pattern"
send "some-command"
...
...
EOF
...
More Bash commands
...

이것은 작동하기 때문에 ...If the string "-" is supplied as a filename, standard input is read instead...


인수없이 호출하면 기본적 -으로 expect읽은 것처럼 여기 가 필요하지 않습니다 stdin. 그러나 명령 프롬프트 ( expectvs expect -) 없이 대화식으로 실행하려는 경우 또는 expect -f "$@"옵션처럼 보이는 경우에도 첫 번째 인수가 파일이 될 위치 와 같은 작업 을 수행하는 경우 유용합니다 (로 시작 -). 이 경우 if $1(주어진 파일)는 -에서 읽습니다 stdin.
Tino

1

sshpassSublime Text 빌드 대상 내에서 Makefile 내에서 사용하려고하면 손상됩니다. 대신 sshpass다음을 사용할 수 있습니다 passh: https://github.com/clarkwang/passh

sshpass당신 과 함께 :

sshpass -p pa$$word ssh user@host

passh당신 과 함께 :

passh -p pa$$word ssh user@host

참고 : 사용을 잊지 마십시오 -o StrictHostKeyChecking=no. 그렇지 않으면 처음 사용할 때 연결이 끊어집니다. 예를 들면 다음과 같습니다.

passh -p pa$$word ssh -o StrictHostKeyChecking=no user@host

참고 문헌 :

  1. SSH 연결에서 expect 스크립트를 사용하여 비밀번호 보내기 명령이 작동하지 않습니다.
  2. ssh에서 엄격한 호스트 키 검사를 비활성화하는 방법은 무엇입니까?
  3. SSH 호스트 키 검사를 비활성화하는 방법
  4. known_hosts 검사가없는 scp
  5. 비밀번호 인증을 사용하는 pam_mount 및 sshfs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.