Bash – password check in bash script calling on expect

automationbashexpectscriptingshell-scripting

Background: I have to copy a file from one server, to over 100 servers in a test environment. once the file is copied, it requires to have the permissions on the file changed/verified. These are all linux servers. most of them have the same password for login, but some may not.

I need help with making a loop in my bash script. It is actually calling on Expect. The area I want to make 'better' or fix, is a few things

  • the part where it expects a password. (the * section), it should quit the script after 1 failed password attempt, and dump the ip to a text file called "fail.txt"
  • ideally there should be a piece that also dumps the ip to a fail.txt if there is no connection to the server.

I tried to write the password piece thinking its a loop, but I'm not really sure if that method of thinking is deal. I tried just adding another "expect Password: " thinking that if it gets the prompt a second time, to exit out, but I had a hard time with getting that to work. Thank you!

#!/bin/bash
while read ip; do

sleep 2
expect <<- DONE
        set timeout 1
        spawn scp yoman.txt root@$ip:/felixtemp
                if above command fails, dump the IP to fail.txt, otherwise continue
        expect yes/no { send yes\r }
        expect Password: { send aaaaaa\r } #if this is good, continue the script from *****
                else                                     #exit the script
                expect Password: { send 033\r }
                expect # { send "echo 'password failed'\r" }
                && dump to a text file called fail.txt
*****   expect # { send "exit\r\r" }
        sleep 1

        set timeout 1
        spawn ssh root@$ip
        sleep 2
        expect yes/no { send yes\r }
        sleep 2
        expect Password: { send aaaaaa\r }
        sleep 5
        expect # { send "cd /felixtemp\r" }
        expect # { send "chown informix:informix yoman.txt\r" }
        expect # { send "chmod 775 yoman.txt\r" }
        expect # { send "sum yoman.txt | grep 10350 && echo 'transfer good' || echo 'transfer bad'\r" }
        expect # { send exit\r }
        sleep 1
DONE

done < ip.txt

Best Answer

If you have to manage hundreds of linux servers you should use a configuration management tool in order to execute these tasks. A very simple configuration management tool is ansible, the only requirement for managed system is python 2.4 or more( http://docs.ansible.com/intro_installation.html#managed-node-requirements ).

Your problem solved with ansible:

1) Define a list of hosts you can define a default password for all the hosts and an other password for some hosts

[hosts_list]
172.17.0.101 ansible_ssh_user=root ansible_ssh_pass=password
172.17.0.102 ansible_ssh_user=root ansible_ssh_pass=oldpassword
172.17.0.103
172.17.0.104

[hosts_list:vars]
ansible_ssh_user=root ansible_ssh_pass=default_password

2) Define a simple playbook containing that tasks that you want execute on the managed nodes

    root@node1:~# cat play.yoman
---
- hosts: hosts_list
  tasks:
  - name: "Build hosts file"
    copy: src=/root/yoman.txt dest=/tmp/felixtemp owner=user group=adm mode=0755

3) Execute the playbook and check the result

root@node1:~# ansible-playbook -i hosts_list play.yoman

PLAY [hosts_list] *************************************************************

GATHERING FACTS ***************************************************************
fatal: [172.17.0.104] => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue
fatal: [172.17.0.103] => SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue
ok: [172.17.0.101]
fatal: [172.17.0.102] => Authentication failure.

TASK: [Build hosts file] ******************************************************
ok: [172.17.0.101]

PLAY RECAP ********************************************************************
           to retry, use: --limit @/root/play.yoman.retry

172.17.0.101               : ok=2    changed=0    unreachable=0    failed=0
172.17.0.102               : ok=0    changed=0    unreachable=1    failed=0
172.17.0.103               : ok=0    changed=0    unreachable=1    failed=0
172.17.0.104               : ok=0    changed=0    unreachable=1    failed=0

You obtain the list of server where the task has executes and the list of server where the task failes with the reasons(unreachable server or wrong password). You obtain also the subset of server where the file, its permission and content wasn't changed because they are already updated