Automating psftp with bash/expect in cygwin.
I have a very minimal script file yftp.exp with code:
#!/usr/bin/expect -f
spawn psftp unixftpsrvr
expect "login as: "
send "myID\r"
expect "Password:"
send "Passw0rd\r"
expect "psftp>"
the output:
$ ./yftp.exp
spawn psftp unixftpsrvr
login as: myID
Using keyboard-interactive authentication.
Enter your UDS
Password: Passw0rd
Remote working directory is /home/myID
psftp>
The password is printed out as clear text!!!
if I run the command directly with psftp. here are the output:
$ psftp unixftpsrvr
login as: myID
Enter your UDS Password:
Remote working directory is /home/myID
psftp>
The password is not displayed at all.
This seems to be more an issue on the expect side.
I am not concerned the password in clear text in my expect script file, I am concerned the password in clear text in the output!
how can I supress the display of password in clear text?
The password may be sent too early before ECHO is turned off. So try adding sleep 1 after expect "Password:".
If that does not work then try like this:
expect "Password:"
log_user 0; # disable logging to stdout
send "password\r"
log_user 1
Related
My purpose is control transferring files between two remote machines. If I could use key-pair it would be much easier but I can't choose the options but passing passwords.
Environments : Local(Mac), Remote_source(Linux), Remote_target(Linux)
Here it is my expect.sh. When I run it, source#source's password: pops up, then target#target's password: and nothing else. No files transferred, no stdout, no error message, just disconnected.
#!/usr/bin/expect
set timeout -1
spawn scp -3 scp://remote_source_user#host:port/home/source/test.txt scp://remote_target_user#host:port/home/target/
expect "remote_source_user#host's password:"
send "SOURCE_PASSWORD\r"
expect "remote_target_user#host's password:"
send "TARGET_PASSWORD\r"
expect eof
When I change the sequence the password (meaning send target password first rather than sending source password first.) it occurs error, so I guess it is working but I have got no idea what is going on internally.
I have tried sshpass but it is not working with several passwords.
I debugged it with -v flag and found out that Connection works perfectly but the problem is the directory.
# in debugging mode
Sink: scp: home/username/test.txt: No such file or directory
It seems not recognizing /home/username/test.txt at the beginning.
so the code should be like below:
#!/usr/bin/expect
set timeout -1
spawn scp -3 scp://remote_source_user#host:port/~/test.txt scp://remote_target_user#host:port/~/
expect "remote_source_user#host's password:"
send "SOURCE_PASSWORD\r"
expect "remote_target_user#host's password:"
send "TARGET_PASSWORD\r"
expect eof
Do not explicitly write your home directory /home/username/ but use /~/.
# The Result
debug1: Sending command: scp -v -r -f ~/test.txt
Sending file modes: C0000 00 test.txt
Sink: C0000 00 test.txt
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
I'm trying to login to a remote host using expect & spawn. While automating this it's going till ssh username#host.example.com and password prompt came and it is terminating wihtout supplying the password. What is wrong with this script ?
#!/usr/bin/expect
set timeout 9
passwrd=PASSWORD
username=USER_NAME
host=host.example.com
/usr/bin/expect << EOF
spawn ssh $username#$host
expect "Password:"
send "$passwrd\r"
interact
You're confusing expect syntax and shell syntax. You want:
#!/usr/bin/expect
set timeout 9
set passwrd PASSWORD
set username USER_NAME
set host host.example.com
spawn ssh $username#$host
expect "Password:"
send "$passwrd\r"
interact
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"
I am creating a script file programmatically and call psftp.exe as follows:
psftp user#hostname.com -pw password -b psftpscript.txt
but it prompts for user input
The server's host key is not cached in the registry. You have no
guarantee that the server is the computer you think it is. The
server's rsa2 key fingerprint is: [ssh-rsa 1024 somekey]
If you trust this
host, enter "y" to add the key to PuTTY's cache and carry on
connecting. If you want to carry on connecting just once, without
adding the key to the cache, enter "n". If you do not trust this host,
press Return to abandon the connection. Store key in cache? (y/n)
I need it to be completely prompt free, automatic.
I tried -batch parameter but it just abandons the connection
I had the same problem with running a unattended script in Windows Server 2008's 'sandbox' like environment. I ended up running the following which enters the y at the prompt for you:
echo y | psftp user#hostname.com -l username -pw password -b psftpscript.txt
Hope this helps!
Note: I only had to run the echo y once and removing it for the 2nd run didn't ask for the key to be cached anymore.
When you run it the first time, it will show you your key for the server.
Copy the key and then on your command line, specify your host key like this:
psftp example.com -hostkey 06:15:d4:3b:e4:e8:23:c0:d6:6d:45:47:7e:bd:8d:74 -l yourusername -pw yourpassword -batch
You can create a file as input containing just a y and carriage return then run
psftp user#hostname.com -pw password -b psftpscript.txt < filename.txt
Thanks to James from http://www.sqlservercentral.com/Forums/Topic281954-9-1.aspx for such a simple solution
This doesn't answer your question directly, but provides a possible workaround:
Launch a command prompt as the user who will be running your script and manually accept the certificate. Then upon future connections, you won't have the issue.
Given your need, beyond what has been stated, this may or may not work. I came to this question with the same problem and ended up resolving it using the approach I've just described.
In .Net, I found that the above method didn't work quite as expected. The trick was to use .Net's built-in input redirection - and not the < operator. Here's what the code looks like now:
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.EnableRaisingEvents = false;
proc.StartInfo.FileName = "c:\\psftp.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.Arguments = strIP + " -v -l " + strUsername + " -pw " + strPassword + " -b " + strBatchFilename;
proc.Start();
StreamWriter myStreamWriter = proc.StandardInput;
myStreamWriter.WriteLine("Y\n"); //override the public key question <---
myStreamWriter.Close();
proc.WaitForExit();
proc.Close();
I had the problem where I didn't have the permission to delete \ rename file over the remote server and the files contains time stamp.
So I needed to download files by name.
The psftp can't accept params (or any way I was aware of) and I couldn't dynamically change the file names according to the current date.
So, from the batch file which I'm calling the psftp commands I created the commands dynamically and with the file with the relevant time stamp.
I could copy only the today files which is better the then copy everything each time.
cd "C:\Files"
echo cd outbound > C:\SFTP\temp.txt
echo mget file_%date:~10,4%%date:~4,2%%date:~7,2%*.csv >> C:\SFTP\temp.txt
echo quit >> C:\SFTP\temp.txt
echo close >> C:\SFTP\temp.txt
C:\SFTP\psftp user#ftp.address.com -b C:\SFTP\temp.txt
close
exit
The "echo cd outbound > C:\SFTP\temp.txt" cleaned the old file and start writing the content of the new file.
The "echo mget file_%date:~10,4%%date:~4,2%%date:~7,2%.csv >> C:\SFTP\temp.txt" resulted in creating the the command: "mget file_20151008.csv " which downloads all files which starts with "file_20151008..." the next 2 rows just ended the action and the line "C:\SFTP\psftp user#ftp.address.com -b C:\SFTP\temp.txt" execute it.
as results temp.txt looks like this:
cd outbound
mget file_20151008*.csv
quit
close
I ended up adding the key to cache by entering 'y' to the prompt. I had to do it only once, and after that no more prompts, it works good.
I think it should also be noted that if you are intending to use psftp in an unattended manner that you MUST include the -batch option. This will ensure that psftp does not provide any interactive prompts.
In the event user input would be required, psftp would abort. (e.g. ask user to cache host key, ask for password, etc.)
This will ensure that your process doesn't 'hang' and allow your automation to alert someone that there is an issue.
I think there is a problem with your command line.
Usage: psftp [options] [user#]host
Try:
psftp -pw password -b psftpscript.txt user#hostname.com
None of the above suggestions worked for me, but I did figure out something that DID work for me.
I made 2 entries in my batch file for it to work.
The first entry causes a connection to cache in the registry.
The second entry will connect automatically because now the hostkey is cached in the registry.
echo y | psftp.exe username#hostname.com -pw password
psftp.exe username#hostname.com -pw password -v -be -batch -b psftp_upload_command.bat