Expect called from bash; Unexpected EOF !
I have few legacy machines which are about to be decommissioned. There is no scope of adding them to puppet/ansible etc. There are no ssh keys either as the user management is done via a third party tool and password is rotated weekly.
So, if I want to execute a script from a centralized jump box on these bunch of servers, expect is the only thing I can use to automate my tasks! I am only trying to fetch information from about ~20 servers. These servers authenticate with a common username, but passwords are different for all. Code sample- Code:
#!/bin/bash The problem starts with the EXPECT bit; specifically with the heredoc invocation. Execution - Code:
$: bash -x test.sh a. exp_internal 1 (adding or removing it does not give additional debugging info) b. made sure my 'map.txt' is a unix file (verified with 'cat -A' and dos2unix to make sure there are no weird characters) c. If I disable the expect block, the rest of the script does not have any errors. What am I missing ? |
this is wrong:
Code:
server= echo $line | awk -F ' ' '{print $1}' Code:
server=$(echo $line | awk -F ' ' '{print $1}') |
Thanks for your attention, @pan64. And so good to see you in the forum.
You are correct. I indeed wrapped them into $(), but must have removed them when I was trying to debug. As the error message is not very helpful, I must have been adjusting this or that. Confirming that wrapping these values in $() does not take away the errors on the expect block. The errors persist. |
I suggest to use shellcheck to analyze your script.
|
Heredocs are not normal, you need a - i.e. <<- EOF. If I remember correctly.
|
That is a great lead. Looks like I should not have indented the HEREDOC :D
Code:
#!/bin/bash The only condition it breaks is when the password contain a '[' character, where it gives this error message - Code:
spawn ssh -q -o StrictHostKeyChecking=no -t admin@server2.domain.com From: https://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M11 If a word contains an open bracket (“[”) then Tcl performs command substitution. To do this it invokes the Tcl interpreter recursively to process the characters following the open bracket as a Tcl script. The script may contain any number of commands and must be terminated by a close bracket (“]”). The result of the script (i.e. the result of its last command) is substituted into the word in place of the brackets and all of the characters between them. There may be any number of command substitutions in a single word. Command substitution is not performed on words enclosed in braces. so how do I tell expect to treat any '[' is $password as only a string and not as a special character ? As soon as I change to this - Code:
send -- {$password\r} Code:
bash -x test.sh Any pointers ? |
here you can find some ideas to easily test your expect script and also probably you can improve it too: https://phoenixnap.com/kb/linux-expect
also you may try: Code:
while IFS= read -r server password |
I tried as you suggested and modified my while loop thus -
Code:
while IFS=' ' read -r server password so how do I tell expect to treat any '[' is $password as only a string and not as a special character ? |
it looks quite simple: https://unix.stackexchange.com/quest...-expect-script
export password and use $env{password} |
Fixed
tried escaping the "[" in the maps.txt with {} but didnt work.
But tried with a simple \, and now it behaves fine. What I do not understand is, bash is reading the file, encounters the escape character and thus treats '[' normally. But '[' is not a special character in bash ( [] is or [[]] is !). And then when the strings go from bash to the expect block, should it not complain again about the rogue [ ? |
Quote:
Code:
password=xyz[ Code:
/bin/expect <<THIS (I'm not that familiar with TCL, but based on the doc page you linked, I believe the problem with using {} to escape is that it only takes effect if the { is the start of the word, but you have the double quote character first.) https://www.gnu.org/software/bash/ma...Here-Documents |
As an experience you can add set -xv to your script (let's say before while) and you will see all commands (line by line) as they are evaluated by the shell and as they are really look like when executed. You can't do that with expect/tcl.
As I mentioned in post #9 using variables will eliminate this issue, because they will not be preprocessed at all, their content will remain intact. |
Quote:
password="$( server="$( ... send "\$env(password)\n" Due to your query I have changed my localhost (windows) password to xyz[ since I am admin :) I tried your script at windows using CYGWIN_NT and sshd server listening at 127.0.0.1 Due to your query I made following changes: 01) Make a backup of /etc/sshd_config before modification if not taken earlier. File: /etc/sshd_config Replace: #PermitRootLogin prohibit-password ... #PubkeyAuthentication yes ... #GSSAPIAuthentication no ... #UsePAM no With: #PermitRootLogin prohibit-password PermitRootLogin no ... #PubkeyAuthentication yes PubkeyAuthentication yes ... #GSSAPIAuthentication no GSSAPIAuthentication yes ... #UsePAM no UsePAM yes Add: PasswordAuthentication yes ChallengeResponseAuthentication no Make a backup of updated file /etc/sshd_config including approved comment from supervisor(Hill Jason I like this technical person a lot from 2005 to 2013 and I have never seen such a technical person throughout my life ever who awarded me during 2008) 02) restart the sshd service at windows /cygdrive/c/WINDOWS/system32/sc.exe stop sshd /cygdrive/c/WINDOWS/system32/sc.exe start sshd My test result: Quote:
Code:
#!/bin/bash No sudo at cygwin Hence I have removed sudo. |
All times are GMT -5. The time now is 09:39 AM. |