Expect script with variable hostname - variables

I would like to use EXPECT script for mount volume after reboot tens of our UBUNTU servers (12.04 & 14.04).
I am not able to figure out how set hostname like variable (for example to grab record from /etc/hostname ) -> I dont wanna create one script (set specific hostname) for each server. My idea is use this script global for my environment.
Following script works fine - but there is set fix hostname
#!/usr/bin/expect -f
set timeout 90
set sudo_pass "Password01
set mount_pass "Password02"
set hostname "test-staging" <<<==== here I set static hostname
# turns off the output to STDOUT
log_user 0
# run mount-script
spawn sudo mount-script
# type sudo pass
expect "password for"
send "$sudo_pass\r"
# type Pass for mount-script
expect "Enter passphrase"
send "$mount_pass\r"
# call & paste hostname
expect "Please provide a hostname for this instance,"
send "$hostname\r"
# type letter Y - for test environment
expect "Is this a test instance? Enter 'Y', otherwise press enter"
send "Y\r"
interact
I tried to google it I found commands for hostname like
send 'lsnrctl status listener_`hostname`\r'
or
send "cat /etc/rc.d/rc.local |grep hostname \r\n"
I tried set them like SET HOSTNAME and I tried call them via command send. Unfortunately, it doesn't work, too.
this is output
.......
dbg1.7>
1: expect "Please provide a hostname for this instance
dbg1.8>
Please provide a hostname for this instance
1: send 'lsnrctl status listener_`hostname`\r'
dbg1.9>
usage: send [args] string
while executing
"send 'lsnrctl status listener_`hostname`\r'"
(file "test01-expect.sh" line 38)
1: exit 1
I am open mind for different solution, too.
thank you

To get the host name of machine, can't you use the terminal command hostname ?
Tcl has a command exec which will execute the command and will return the result.
set host_name [exec hostname]
or, equivalently,
set host_name [ exec cat /etc/hostname]
Instead of saving it into a variable, this can be directly even used in the send command as,
expect "Please provide a hostname for this instance,"
send "[exec hostname]\r"
Reference : exec

Related

Expect script not working and terminal closes immediately

I don't know what's wrong with the script. I set up a new profile on Iterm terminal to run the script, but it never works and closes immediately. Here's the script:
#!/usr/bin/expect -f
set timeout 120
set secret mysecret
set username asdf
set host {123.456.789.010}
set password password123
log_user 0
spawn oathtool --totp --base32 $secret
expect -re \\d+
sleep 400
set otp $expect_out(0,string)
spawn ssh -2 $username#$host
expect "*assword:*"
send "$password\n"
expect "Enter Google Authenticator code:"
send "$otp\n"
interact
First, test you ssh connection with:
ssh -v <auser>#<apassword>
That will validate the SSH session works.
Make sure to not use ssh -T ..., since you might need a terminal for expect commands to work.
Second, add at least an echo at the beginning of the script, to see if it is called:
puts "Script running\r"
Third, see if a bash script, with part of it using expect as in here, would work better in this case

How to check SSH credentials are working or not

I have a large number of devices around 300
I have different creds to them
SSH CREDS, API CREDS
So as I cannot manually SSH to all those devices and check the creds are working or not
I am thinking of writing a script and pass the device IP's to the script and which gives me as yes as a result if the SSH creds are working and NO if not working.
I am new to all this stuff! details will be appreciated!
I will run this script on a server from where I can ssh to all the devices.
Your question isn't clear as to what sort of credentials you use for connecting to each host: do all hosts have the same connection method, for instance?
Let's assume that you use ssh's authorised keys method to log in to each host (i.e. you have a public key on each host within the ~/.ssh/authorized_keys file). You can run ssh with a do nothing command against each host and look at the exit code to see if the connection was successful.
HOST=1.2.3.4
ssh -i /path/to/my/private.key user#${HOST} true > /dev/null 2>&1
if [ $? -ne 0]; then echo "Error, could not connect to ${HOST}"; fi
Now it's just a case of wrapping this in some form of loop where you cycle through each host (and choose the right key for each host, perhaps you could name each private key after the name or IP address of the target host). The script will go out all those hosts for which a connection was not possible. Note that this script assumes that true is available on the target host, otherwise you could use ls or similar. We pipe all output to /dev/null/ as we're only interested in the ability to connect.
EDIT IN RESPONSE TO OP CLARIFICATION:
I'd strongly recommend not using username/password for login, as the username and password will likely be held in your script somewhere, or even in your shell history, if you run the command from the command line. If you must do this, then you could use expect or sshpass, as detailed here: https://srvfail.com/how-to-provide-ssh-password-inside-a-script-or-oneliner/
The ssh command shown does not spawn a shell, it literally logs in to the remote server, executes the command true (or ls, etc), then exits. You can use the return code ($? in bash) to check whether the command executed correctly. My example shows it printing out an error message for non-zero return codes, but to print out YES on successful connection, you could do this:
if [ $? -eq 0]; then echo "${HOST}: YES"; fi

sh script within an ssh session not returning value

I have the following sh script code that accesses my local router via SSH in order to find the real IP address of the router (vs. apparent IP created by my VPN).
The code works and I receive no errors but it doesn't return the string I would expect, ie. "External IP is 99.99.99.99.".
If I execute each of the 3 commands separately within Terminal (ssh, getrealip.sh & echo) it works perfectly.
Anyone know what I am missing here?
Running the script on Mac OS accessing an Asus router. Script is to be run from a TextBar item.
#!/bin/sh
myip=$(ssh admin#192.168.1.1 'myip=$(/usr/sbin/getrealip.sh); echo $myip')
echo "$myip"
exit
Should result in "External IP is 99.99.99.99." string but actually returns null.
I apologize for not have the most helpful answer, but from my experience, the ' literally interprets string values. So you'll get something like this:
bash-4.3# echo '$(hostname -I)'
$(hostname -I)
Try replacing ' characters with "
Also, be aware that subshells will be interpreted BEFORE the ssh call. so your PC will attempt to run the script before it connects to your router.
Maybe I'm not reading the question right, but you may not even need the subshell. IDK if the version of SSH uses the -t option. but I'd recommend you change your SSH command to
myip=$(ssh admin#192.168.1.1 -t "sh /usr/sbin/getrealip.sh;")

Tcl Expect fails spawning SSH to server but SSH from command line works

I have some code that I'm using to connect to a server and perform some commands. The code is as follows:
#!/usr/bin/expect
log_file ./log_std.log
proc setPassword {oldPass newPass} {
send -- "passwd\r"
expect "* Old password:"
send -- "$oldPass\r"
expect "* New password:"
send -- "$newPass\r"
expect "* new password again:"
send -- "$newPass\r"
}
set server [lindex $argv 0]
spawn /bin/ssh perfgen#$server
# Increase buffer size to support large text responses
match_max 100000
# Conditionally expects a prompt for host authenticity
expect {
"*The authenticity of host*" {
send -- "yes\r"
}
}
What I find very strange is that when I SSH from my command line the SSH command works no problem. However, when I SSH from the shell script I get the following error:
spawn /bin/ssh perfgen#192.168.80.132
ssh: Could not resolve hostname 192.168.80.132
: Name or service not known
The same script runs against 3 servers, but 2 of the 3 servers always fail. However, if I try logging into the servers manually do do the work all three servers pass.
Any idea what might be happening here? I'm completely stumped. This code was working up until about 2 weeks ago and according to the server administrator nothing has changed on the server-side config.
Trimming any whitespace seemed to solve the issue:
set serverTrimmed [string trim $server]

ssh to cisco ASA and store output to a file

I am having trouble writing a shell-script for ssh into cisco ASA and store command output in a text file.
1.key exchange not needed in the script as it is not first time log in.
2. from my centOS server it should log into cisco ASA with ssh usr#serverip, run "en", send en password
and then run some command say "show version" and store the output to a text file in my server. I tried both shell script and the use of expect, not successful in either. Please help.
Thanks a lot in advance.
This is a small code written in python which does the work for you. Python is by default installed in your CentOS. Just save the code in file name it as .py and run it with "python .py". Let me know if this helps.
import pexpect
try:
hostname= 'yourhostname/ip of firewall'
username= 'your username'
commandTorun = 'Enter your command here'
password= 'your password'
enable= 'your enable password'
ssh = 'ssh ' + username + '#' +hostname
s=pexpect.spawn(ssh)
s.expect('word')
s.sendline(password)
s.expect('>');
s.sendline('en')
s.expect('word')
s.sendline(enable)
s.expect('#')
s.sendline('configure terminal')
s.expect('#')
s.sendline('pager 0')
s.expect('#')
s.sendline(commandTorun)
s.expect('#')
output = s.before
#You can save the output however you want here. I am printing it to the CLI.
s.sendline('exit')
s.expect('#')
s.sendline('exit')
s.expect(pexpect.EOF)
print output
except Exception, e:
print "The Script failed to login"
print str(e)
I'm not familiar with CentOS, but I have done this on Windows using Plink - a command line version of PuTTY. http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html (Edit: just checked and it appears plink exists as a .rpm file and is available on the repositories. The link provided also has source code if manual compile is your thing.)
The option -m allows you to specify a command script, -ssh forces ssh protocol, -l is the remote user and -pw is the remote password.
Here is the command:
plink.exe -ssh -l user -pw pass -m "path_to_script/script.txt" ip_of_asa > outputfile.txt
In the script.txt file you simply a list of commands including the enable command and hardcoded password:
en
enable_password
show ver
exit
Note, there are spaces in there to get the full "show ver" if multiple pages. The output uses the ">" to redirect output to file.
Hope this helps!
This works.
#!/usr/bin/expect
set remote_server [lrange $argv 0 0]
set timeout 10
spawn ssh -M username#$remote_server
while 1 {
expect {
"no)?" {send "yes\r"}
"denied" {
log_file /var/log/expect_msg.log
send_log "Can't login to $remote_server. Check username and password\n";
exit 1
}
"telnet:" {
log_file /var/log/expect_msg.log
send_log "Can't connect to $remote_server via SSH or Telnet. Something went definitely wrong\n";
exit 2
}
"failed" {
log_file /var/log/expect_msg.log
send_log "Host $remote_server exists. Check ssh_hosts file\n";
exit 3
}
timeout {
log_file /var/log/expect_msg.log
send_log "Timeout problem. Host $remote_server doesn't respond\n";
exit 4
}
"refused" {
log_file /var/log/expect_msg.log
send_log "Host $remote_server refused to SSH. That is insecure.\n"
log_file
spawn telnet $remote_server
}
"sername:" {send "username\r"}
"assword:" {send "password\r"}
">" {enable}
"#" {break}
}
}
send "terminal length 0\r"
expect "#"
send "show running-config\r"
log_file /opt/config-poller/tmp/poller.trash/$remote_server
expect "#"
send "exit\n"; exit 0
If you are accessing your router through your local machine, then you can create an expect script and configure tftp in your local machine.
The script would be like.
#!/usr/bin/expect-f
spawn telnet Router_IP
expect "word"
sent "password"
expect "word"
sent "copy running-config tftp://$tftp/$config\n\n" #edit this line wrt system's tftp configurations.
expect "word"
send "\n"