셸 과 expect, ssh 에 대하 여

12949 단어 expectssh
전에 일부 큰 신 들 이 말 하 는 것 을 보 았 다. 운영 차원 으로서 시스템 엔지니어 의 능력 중 하 나 는 그 가 몇 대의 기 계 를 관리 할 수 있 는 지, 그 가 어느 정도 자동화 할 수 있 는 지, 그 가 얼마나 게 을 러 질 수 있 는 지 하 는 것 이다.그래서 나 도 반 문 에 도끼 질 하 러 왔 기 때문에 이 문장 이 생 겼 다.
현재 고도 로 발전 하고 있 는 it 사회 에는 이미 많은 자동화 관리 프로그램 이 있다. 예 를 들 어 Puppet, Salt, func, Capistrano.그러나 존 재 는 합 리 적 인 것 입 니 다. 당신 은 높 고 큰 것 이 있 습 니 다. 저도 토비 원 이 있 습 니 다. 빠 르 고 간단 한 관리 에 비해 소량의 Liux 기계, ssh 와 expect 는 매우 좋 습 니 다.
expect 가 뭐 예요?
그 는 uucp (Unix to Unix Copy Protocol) 의 전송/예상 시퀀스 를 기반 으로 한 프로그램 입 니 다.
The name "Expect"comes from the idea of send/expect sequences popularized by uucp, kermit and other modem control programs. However unlike uucp, Expect is generalized so that it can be run as a user-level command with any program and task in mind. Expect can actually talk to several programs at the same time. For example, here are some things Expect can do:
  • Cause your computer to dial you back, so that you can login without paying for the call.
  • Start a game (e.g., rogue) and if the optimal configuration doesn't appear, restart it (again and again) until it does, then hand over control to you.
  • Run fsck, and in response to its questions, answer "yes", "no"or give control back to you, based on predetermined criteria.
  • Connect to another network or BBS (e.g., MCI Mail, CompuServe) and automatically retrieve your mail so that it appears as if it was originally sent to your local system.
  • Carry environment variables, current directory, or any kind of information across rlogin, telnet, tip, su, chgrp, etc.

  • 가장 간단 한 차원 에서 말하자면, Expect 의 작업 방식 은 유 니 버 설 화 된 Chat 스 크 립 트 도구 와 같다.Chat 스 크 립 트 는 컴퓨터 간 연결 이 필요 할 때 특정 로그 인 세 션 의 자동 화 를 위해 UUCP 네트워크 에 최초 로 사 용 됩 니 다.
    Chat 스 크 립 트 는 일련의 expect - send 쌍 으로 구성 되 어 있 습 니 다. expect 대기 출력 에서 특정한 문 자 를 출력 합 니 다. 보통 프롬프트 다음 에 특정한 응답 을 보 냅 니 다.예 를 들 어 아래 의 Chat 스 크 립 트 는 표준 출력 을 기다 리 는 로그 인 문자열 을 구현 하고 somebody 를 사용자 이름 으로 보 냅 니 다.그리고 Password: 프롬프트 를 기다 리 고 응답 sillyme 을 보 냅 니 다.
    그래서 expect 의 업무 절 차 는 채 팅 과 유사 한 절차 입 니 다.
    A跟B说 hello
    B发现A跟他说hello,然后就回复hi
    然后A XXXXX
    然后B 发现A 在说XXXXX,所以就回复OOOOO
    .......
    

    이해 하면 이렇게 이해 할 수 있다. 비록 완전 하 지 는 않 지만 그 의 미 를 잃 지 않 는 다.
    그리고 expect 가 어떻게 작용 하 는 지 알 게 된 이상 우리 의 자동화 관리 디자인 을 구상 할 수 있 습 니 다. expect 의 디자인 원 리 는 바로 '상호작용 식' 을 처리 하기 위해 '상호작용 식' 을 처리 한 후에 인위적인 관여 가 적 고 자 연 스 럽 게 자동 화 를 실현 하기 때 문 입 니 다.
    일반 expect 사용
    #!/usr/bin/expect
    
    set timeout 5
    
    spawn ssh 192.168.6.136 -p 1024
    
    expect "password" {send "123passwd
    "} expect "Last login" {send " ifconfig |grep eth0 -A3
    "} expect eof exit
  • #!/usr/bin/expect 는 expect 를 호출 하 는 쓰기 입 니 다. 이것 은 일반적인 셸 과\#!/빈/bash 는 다 릅 니 다. 여기 서 의 미 는 다음 과 같은 내용 이 어떤 방식 으로 실행 되 는 지 입 니 다. expect 를 쓰 는 것 은 expect 의 방식 이 고 bash 를 쓰 는 것 은 bash 입 니 다.
  • spawn 은 프로 세 스 를 만 드 는 것 입 니 다. expect 를 사용 할 때 expect 프로 세 스 를 실행 하 는 것 입 니 다. spwan 은 이러한 프로 세 스 를 만들어 야 한 다 는 뜻 입 니 다. create 로 이해 하 셔 도 됩 니 다. 여 기 는 ssh 연결 프로 세 스 를 만 드 는 것 입 니 다. 뒤의 쓰기 방법 은 일반 ssh 연결 실행 명령 과 다 름 없습니다.
  • timeout 은 이 expect 동작의 생존 시간 을 나타 낸다. 나의 이해 에 따 르 면 예 를 들 어 5 초 로 설정 하면 expect 를 한 번 실행 한 후에 5 초 를 기 다 려 야 한다.
  • expect eof 와 exit 는 eof 가 감지 되면 exit 를 실행 하고 프로그램 을 종료 하 는 것 을 말한다.

  • 고 급 스 러 움 은 조금... 으로 바 꿀 수 있다.
    우 리 는 일반적인 ssh 의 정상 적 인 상호작용 이 어떤 상황 이 있 는 지 관찰 합 니 다. 첫 번 째 연결 알림 은 성공 적 으로 연결 한 후에 knowhost 가 생 성 되 고 앞으로 힌트 를 주지 않 을 것 입 니 다.
    ssh 192.168.6.136 -p 1024
    The authenticity of host '[192.168.6.136]:1024 ([192.168.6.136]:1024)' can't be established.
    RSA key fingerprint is 7d:68:97:bc:f8:c1:b7:8a:a9:98:5a:03:4a:77:b9:eb.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '[192.168.6.136]:1024' (RSA) to the list of known hosts.
    [email protected]'s password:
    

    정상 연결 알림:
    ssh 192.168.6.136 -p 1024
    [email protected]'s password: 
    

    연결 이 거부 되 었 습 니 다. ssh 가 열 리 지 않 았 거나 포트 가 잘못 되 었 거나 iptables 제한 이 있 을 수 있 습 니 다.
    ssh 192.168.6.136 
    ssh: connect to host 192.168.6.136 port 22: Connection refused
    

    연결 주소 없 음:
    ssh sadas 
    ssh: Could not resolve hostname sadas: Name or service not known
    

    그래서 이렇게 고 칠 수 있다.
    #!/usr/bin/expect
    
    set timeout 5
    
    spawn ssh 192.168.6.136 -p 1024
    
    expect {
        "Connection refused" exit
        "Name or service not known" exit
        "continue connecting" {send "yes\r";exp_continue}
        "password:" {send "123passwd\r";exp_continue}
        "Last login" {send " ifconfig |grep eth0 -A3
    "} } expect eof exit
  • 그래서 expect 를 하나 로 수집 한 다음 switch - case 와 같은 모드 를 사용 하여 일치 하 는 것 을 터치 하고 다음 동작 을 수행 하려 면 exp 를 추가 해 야 합 니 다.contine, 사실 여 기 는 일반 프로그램 에서 순환 을 제어 하 는 contine 과 같은 용법 입 니 다.

  • 이것 은 실행 결과 입 니 다.
    [root@localhost test_shell_expect]# ./test3.sh  
    spawn ssh 192.168.6.136 -p 1024
    [email protected]'s password: 
    Last login: Wed Feb 25 07:07:42 2015 from 192.168.6.127
    ifconfig |grep eth0 -A3
    [root@wohost ~]#  ifconfig |grep eth0 -A3
    eth0    Link encap:Ethernet  HWaddr 00:0C:29:DE:E9:90  
            inet addr:192.168.6.136  Bcast:192.168.6.255  Mask:255.255.255.0
            inet6 addr: fe80::20c:29ff:fede:e990/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    

    조금 만 더 고 급 스 럽 게 하면 이렇게 변수 정의 와 전 삼 기능 을 지원 할 수 있 습 니 다.
    #!/usr/bin/expect 
    
    set timeout 5
    
    set pw "123passwd"
    set host [lindex $argv 0]
    
    spawn ssh $host -p 1024
    
    expect {
        "Connection refused" exit
        "Name or service not known" exit
        "continue connecting" {send "yes\r";exp_continue}
        "password:" {send "$pw\r";exp_continue}
        "Last login" {send " ifconfig |grep eth0 -A3
    "} } expect eof exit
  • set 는 변 수 를 정의 하 는 것 이 고 전 삼 은 lindex $argv 0 방식 을 사용 하 는 것 입 니 다. $argv 는 매개 변수 항목 배열 을 말 합 니 다. lindex 는 매개 변수 항목 배열 의 목록 을 생 성 한 다음 에 0 은 첫 번 째 값 을 사용 하 는 것 을 대표 합 니 다. 그러나 여기 서 작은 의문 이 있 습 니 다. debug 모드 를 참고 하면 argv [0] =/usr/bin/expect argv [1] 를 볼 수 있 습 니 다.= - d argv [2] =./test 3. sh argv [3] = 192.168.6.136, 첫 번 째 값 은 argv [0] =/usr/bin/expect 여야 하지만 프로그램 은 192.168.6.136 을 얻 을 수 있 습 니 다. 제 가 일시 적 으로 이해 하 는 것 은 제 가 명령 을 수행 하 는 첫 번 째 매개 변수 입 니 다. 예 를 들 어./test 3. sh 192.168.6.136 입 니 다. 그래서 첫 번 째 매개 변 수 는 192.168.6.136 입 니 다. 이렇게 유추 합 니 다.

  • 효과:
    ./test3.sh 192.168.6.136
    spawn ssh 192.168.6.136 -p 1024
    [email protected]'s password: 
    Last login: Wed Feb 25 07:11:17 2015 from 192.168.6.127
     ifconfig |grep eth0 -A3
    [root@wohost ~]#  ifconfig |grep eth0 -A3
    eth0    Link encap:Ethernet  HWaddr 00:0C:29:DE:E9:90  
            inet addr:192.168.6.136  Bcast:192.168.6.255  Mask:255.255.255.0
            inet6 addr: fe80::20c:29ff:fede:e990/64 Scope:Link
            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
    

    그리고 셸 에 맞 춰 순환 을 하면 대량 관 리 를 간단하게 할 수 있 습 니 다.
    [root@localhost test_shell_expect]# cat test2.sh 
    #!/bin/bash
    
    while read host
    do           
        ./test1.exp $host 
    done 

    큰 성 과 를 거두다.
    troubleshooting
  • debug 모드 를 열 고 - d 를 사용 하면 디 버 깅 을 편리 하 게 하고 expect 의 실행 과정 을 볼 수 있 습 니 다.

  • !/usr/bin/expect -d
    출력 효 과 는 다음 과 같 습 니 다:
    ./test3.sh 192.168.6.136
    expect version 5.44.1.15
    argv[0] = /usr/bin/expect  argv[1] = -d  argv[2] = ./test3.sh  argv[3] = 192.168.6.136  
    set argc 1
    set argv0 "./test3.sh"
    set argv "192.168.6.136"
    executing commands from command file ./test3.sh
    spawn ssh 192.168.6.136 -p 1024
    parent: waiting for sync byte
    parent: telling child to go ahead
    parent: now unsynchronized from child
    spawn: returns {7991}
    
    expect: does "" (spawn_id exp4) match glob pattern "Connection refused"? no
    "Name or service not known"? no
    "continue connecting"? no
    "password:"? no
    "Last login"? no
    [email protected]'s password: 
    expect: does "[email protected]'s password: " (spawn_id exp4) match glob pattern "Connection refused"? no
    "Name or service not known"? no
    "continue connecting"? no
    "password:"? yes
    expect: set expect_out(0,string) "password:"
    expect: set expect_out(spawn_id) "exp4"
    expect: set expect_out(buffer) "[email protected]'s password:"
    send: sending "123passwd\r" to { exp4 }
    expect: continuing expect
    
    expect: does " " (spawn_id exp4) match glob pattern "Connection refused"? no
    "Name or service not known"? no
    "continue connecting"? no
    "password:"? no
    "Last login"? no
    
    
    expect: does " \r
    " (spawn_id exp4) match glob pattern "Connection refused"? no "Name or service not known"? no "continue connecting"? no "password:"? no "Last login"? no Last login: Wed Feb 25 07:14:06 2015 from 192.168.6.127 expect: does " \r
    Last login: Wed Feb 25 07:14:06 2015 from 192.168.6.127\r\r
    " (spawn_id exp4) match glob pattern "Connection refused"? no "Name or service not known"? no "continue connecting"? no "password:"? no "Last login"? yes expect: set expect_out(0,string) "Last login" expect: set expect_out(spawn_id) "exp4" expect: set expect_out(buffer) " \r
    Last login" send: sending " ifconfig |grep eth0 -A3
    " to { exp4 } ifconfig |grep eth0 -A3 [root@wohost ~]# ifconfig |grep eth0 -A3 eth0 Link encap:Ethernet HWaddr 00:0C:29:DE:E9:90 inet addr:192.168.6.136 Bcast:192.168.6.255 Mask:255.255.255.0 inet6 addr: fe80::20c:29ff:fede:e990/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

    과학 보급 시간
    1. expect 에 관 한 - f 와 -
    - f 사실 추가 할 수 있 습 니 다. 그 는 단지 파일 에서 명령 을 읽 는 것 이 라 고 말 했 기 때 문 입 니 다. 그 는 옵션 입 니 다.\# 만 사용 하고 있 습 니 다!할 때 는 내 가 테스트 하 는 것 에 따라 사실 넣 지 않 아 도 된다.
    The -f flag prefaces a file from which to read commands from. The flag itself is optional as it is only useful when using the #! notation (see above), so that other arguments may be supplied on the command line. (When using Expectk, this option is specified as -file.)
    
    By default, the command file is read into memory and executed in its entirety. It is occasionally desirable to read files one line at a time. For example, stdin is read this way. In order to force arbitrary files to be handled this way, use the -b flag. (When using Expectk, this option is specified as -buffer.)
    

    -- 제한 파 라미 터 는 여기까지.하 긴, 넣 어도 되 고 안 넣 어도 돼.
    may be used to delimit the end of the options. This is useful if you want to pass an option-like argument to your script without it being interpreted by Expect. This can usefully be placed in the #! line to prevent any flag-like interpretation by Expect. For example, the following will leave the original arguments (including the script name) in the variable argv.
    
    #!/usr/local/bin/expect --
    Note that the usual getopt(3) and execve(2) conventions must be observed when adding arguments to the #! line.
    

    2. send 에 관 한\r 와 --
    expect 의 문자 처 리 는 줄 바 꿈 문자 가 없 기 때문에 추가 적 으로 추가 해 야 합 니 다.\r 대 표 는 반환 문자 입 니 다. 대 표 는 여기까지 입력 하고 돌아 가 야 합 니 다. 사실은 효 과 는 리 턴 을 누 르 는 것 과 비슷 합 니 다. 왜 어떤 곳 은\r 를 사용 하 는 지, 어떤 곳 은 사용 하 는 지, 사실은 출력 형식 이 보기 좋 을 뿐 사실은\r 와 같 기 때문에 빈 줄 이 하나 더 있 습 니 다.
    Sends string to the current process. For example, the command
    send "hello world\r"
    
    sends the characters, h e l l o  w o r l d  to the current process. (Tcl includes a printf-like command (called format) which can build arbitrarily complex strings.)
    Characters are sent immediately although programs with line-buffered input will not read the characters until a return character is sent. A return character is denoted "\r".
    

    다음 매개 변 수 를 문자열 로 바 꾸 도록 강제 하 는 것 으로 강제 텍스트 화 효과 와 유사 합 니 다.
    The -- flag forces the next argument to be interpreted as a string rather than a flag. Any string can be preceded by "--" whether or not it actually looks like a flag. This provides a reliable mechanism to specify variable strings without being tripped up by those that accidentally look like flags. (All strings starting with "-" are reserved for future options.)
    

    참조 참조:
  • http://bbs.chinaunix.net/thread-594417-1-1.html
  • http://www.admin-magazine.com/Articles/Automating-with-Expect-Scripts
  • http://www.tcl.tk/man/expect5.31/expect.1.html
  • http://linux.about.com/library/cmd/blcmdln_lindex.htm

  • 원본 링크:http://www.godblessyuan.com/2015/02/25/shell_expect_ssh/

    좋은 웹페이지 즐겨찾기