Trying to achieve a goal of running putty's plink -telnet via Tcl Expect.
When i do a regular:
plink -telnet 127.1.1.2
i get an output of the process and am able to properly conduct what i have planned.
But when i try the same from Tcl Expect:
% package require Expect
5.43.2
% exp_internal 1
% spawn plink -telnet 127.1.1.2 -s
16196
% expect -nocase login
expect: does "" (spawn_id exp4) match glob pattern "login"? no
expect: timed out
there is simply no response from the piped process.
Tcl: ActiveTcl 8.6(x86)
Expect: 5.43.2
Putty: latest x86
Win10 x64
Or, if possible, could you please suggest another telnet client which works correct with tcl's expect(currently using Win7 native, but want to try something different, and yes, i know that "telnet is just a telnet", but have crash issues with the native one).
Related
I try to connect to my router using ssh in order to automatically extract some logs from it.
I developed this code below :
#!/usr/bin/expect -f
spawn ssh root#192.168.1.1
expect "Are you sure you want to"
send -- "yes\r"
expect "password"
send -- "root\r"
expect "\#"
send -- "ls\r"
expect "\#"
the problem is I expected a garbage before the prompt in the output log.
spawn ssh root#192.168.1.1
The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established.
RSA key fingerprint is SHA256:6aeE74qXMeQzg0SGJBZMIa0HFQ5HJrNqE5f3XZ6Irds.
Are you sure you want to continue connecting (yes/no)? yes
Failed to add the host to the list of known hosts (/home/amin/.ssh/known_hosts).
root#192.168.1.1's password:
BusyBox v1.30.1 () built-in shell (ash)
OpenWrt Version: ALPHA
OpenWrt base: 19.07
------------------------------------
]0;root#openwrt: ~root#openwrt:~# ls
[0;0mnetwork[m
]0;root#openwrt: ~root#openwrt:~#
what's the main cause of this issue? How I can fix it?
The problem is that there are terminal escape sequences being issued, probably to control what colour the terminal uses. The easiest fix is to set the terminal type (an environment variable) to something that doesn't support colour before doing the spawn. Perhaps this will do the trick:
set env(TERM) "dumb"
If that doesn't work (it depends on exactly what is in someone's .bashrc) then you can just override the PS1 environment variable on the remote side with your first command after logging in.
# etc for logging in
expect "# "
send "PS1='# '\r"
expect "# "
# Everything should be right from here on
I’m trying to run/load sql file into mysql database using this golang statement but this is not working:
exec.Command("mysql", "-u", "{username}", "-p{db password}", "{db name}", "<", file abs path )
But when i use following command in windows command prompt it’s working perfect.
mysql -u {username} -p{db password} {db name} < {file abs path}
So what is the problem?
As others have answered, you can't use the < redirection operator because exec doesn't use the shell.
But you don't have to redirect input to read an SQL file. You can pass arguments to the MySQL client to use its source command.
exec.Command("mysql", "-u", "{username}", "-p{db password}", "{db name}",
"-e", "source {file abs path}" )
The source command is a builtin of the MySQL client. See https://dev.mysql.com/doc/refman/5.7/en/mysql-commands.html
Go's exec.Command runs the first argument as a program with the rest of the arguments as parameters. The '<' is interpreted as a literal argument.
e.g. exec.Command("cat", "<", "abc") is the following command in bash: cat \< abc.
To do what you want you have got two options.
Run (ba)sh and the command as argument: exec.Command("bash", "-c", "mysql ... < full/path")
Pipe the content of the file in manually. See https://stackoverflow.com/a/36383984/8751302 for details.
The problem with the bash version is that is not portable between different operating systems. It won't work on Windows.
Go's os.exec package does not use the shell and does not support redirection:
Unlike the "system" library call from C and other languages, the os/exec package intentionally does not invoke the system shell and does not expand any glob patterns or handle other expansions, pipelines, or redirections typically done by shells.
You can call the shell explicitly to pass arguments to it:
cmd := exec.Command("/bin/sh", yourBashCommand)
Depending on what you're doing, it may be helpful to write a short bash script and call it from Go.
I want to use TCL with Expect at my Windows 8 64-bit OS
I've installed 32-bit version of TCL from ActiveState, installed Expect via teacup, and use 32-bit version of plink (cause native Windows Telnet client doesnt work).
Testing scripts actully work, but they print no output to console, just run silently.
Here is example
package require Expect
log_user 1
spawn plink -telnet -P 2001 10.10.10.100
send "conf t\r"
send "hostname yyyy\r"
send "int loo100\r"
send "int loo101\r"
send "int loo102\r"
send "exit\r"
If i run it directly from shell command by command i receive just some number after spawn. Please, look at screenshot.
What is the problem ?
Tnkx
I need to write a TCL program through which I shall be able to login to the remote server and then execute commands on the remote server; also I need to get the output from the remote server.
EDIT:
Thanks Kostix for the reply. My requirement says that the TCL script should be able to login to the remote server. I am planning to send the password thru the expect mechanism, and after that I am planning to send the commands. My sample code goes like this:
set prompt "(%|>|\#|\\\$) #"
spawn /usr/bin/ssh $username#$server
expect {
-re "Are you sure you want to continue connecting (yes/no)?" {
exp_send "yes\r"
exp_continue
#continue to match statements within this expect {}
}
-nocase "password: " {
exp_send "$password\r"
interact
}
}
I am able to login with this but dont know how to extend this code to send commands. I've tried few methods, but didn't work out.
Since you're about to use SSH, you might not need neither Tcl nor Expect to carry out this task at all: since SSH stands for "Secure SHell", all you need to do to execute commands remotely is to tell SSH what program to spawn on the remote side after logging in (if you do not do this, SSH spawns the so-called "login shell" of the logged in user) and then SSH feeds that program what you pass the SSH client on its standard input and channels back what the remote program writes to its standard output streams.
To automate logging via SSH, several ways exist:
Authentication using public keys: if the private (client's) key is not protected by a password, this method requires no scripting at all — you just tell the SSH client what key to use.
"Keyboard interactive" authentication (password-based). This is what most people think SSH is all about (which is wrong). Scripting this is somewhat hard as SSH insists on getting the password from a "real terminal". It can be tricked to beleive so either through using Expect or simply by wrapping a call to the SSH client using the sshpass program.
Both the SSH client and the server might also support Kerberos-based or GSSAPI-based authentication. Using it might not require any scripting as it derives the authentication credentials from the system (the local user's session).
So the next steps to carry out would be to narrow your requirements:
What kind of authentication has to be supported?
What program should perform the commands you intend to send from the client? Will that be a Unix shell? A Tcl shell? Something else?
Should that remote command be scripted using some degree of interactivity (we send something to it then wait for reply and decide what to send next based on it) or batch-style script would be okay?
Before these questions are answered, the inital question has little sense as it's too broad and hence does not meet stackoverflow format.
Commands on the server can be executed either using exec command like this,
set a [exec ls -lrta]
puts $a
[OR] The expect and execute loop can be continued as above;
I am making a proc using which linux commands can easily be run;
package require Expect
proc ExecCommand {username server password cmd } {
spawn /usr/bin/ssh $username#$server
expect {
".*(yes/no)? " {exp_send "yes\r" ; exp_continue}
".*password: " {exp_send "$password\r";exp_continue}
".*$ " {exp_send -i $spawn_id "$cmd \r";
expect {
".*$ " { return 1; close }
}
}
}
}
set result [ExecCommand "admin" "0" "qwerty" "ls"]
if {$result > 0 } {
puts "Command succesfully executed\n"
} else {
puts "Failed to execute\n"
}
I am trying to write an expect script that will do the following..
open up 13 terminal windows (gnome-terminal, xterm etc)
each window connects to a terminal server via ssh (ssh InReach#10.1.6.254)
and is provided the password via expect.
i can get this to work fine in a single window. the problem i am having though is getting the input passed over to each window.
for instance...
i can do
set timeout -1
spawn gnome-terminal -x ssh InReach#10.1.6.254
inside of a while loop and get my 13 windows. but i would like each one to be logged in automatically via expect.
You can try a slightly different approach. Instead of opening the terminal windows in the expect script, open them in a basic shell script, and have each terminal run an expect script to start a single SSH session.
So the expect script could be as simple as this:
#!/usr/bin/expect -f
spawn ssh InReach#10.1.6.254
# ... provide password ...
interact
And the shell script:
#!/bin/sh
for a in `seq 1 13`; do
gnome-terminal -x ./expect_script
done
When you spawn, you need to cache the $spawn_id value which is set by the attempt.
e.g.
if [catch "spawn ssh -l mtc $ub1_ip_address" ub1_pid] {
Log $ERROR "Unable to spawn ssh to Xubuntu.\n$ub1_pid\n"
return 0
}
set stored_id $spawn_id
To send a command to one terminal session in particular, do
send -i $stored_id "command"
Then, before you contact each, you must first do
expect {
-i $stored_id
[ ... your regexes, globs, etc. ... ]
}
You can find some add'l info http://wiki.tcl.tk/11583
I would also suggest making use of gnome-terminal's ability to specify multiple tabs, including an indication of which is the currently-active one, and a command to be executed. gnome-terminal --help-all is helpful (no pun intended).