How can I not generate the substring "...[C[C[C[0k" after issued comands trough expect scripts?
For example, I have the following lines in an expect script:
#set variables, parameters etc
...
spawn telnet $IP $PORT
expect -nocase "name:"
send -- "$USER\r"
expect -nocase "password:"
send -- "$PASS\r"
expect -re "$prompt"
send -- "terminal length 0\r"
expect -re "$prompt"
send -- "show vlan\r"
expect -re "$prompt"
send -- "logout\r"
expect eof
After execution I receive the undesirable substrings:
Username:[C[C[C[C[C[C[C[C[C[0Kadmin
Password:[C[C[C[C[C[C[C[C[C[0K**************
switch#
[C[C[C[C[C[C[C[C[C[0Kterminal length 0
switch#[C[C[C[C[C[C[C[C[C[0Kshow vlan
...
#'show vlan' command result here
...
switch#[C[C[C[C[C[C[C[C[C[0Klogout
Connection closed by foreign host.
Does anyone have a tip on how can I not generate these "[C[C[C[C[C[C[C[C[C[0K" strings? Other issue is that I cannot use other tool(sed, awk, tr etc) to remove the strings, I need that expect not generate then at first place.
Expect is not generating these, it is the Cisco telnet service that you are connecting to. It sends escape sequences to do stuff like changing colours.
You could try changing the TERM variable before calling expect, or setting it in your expect script before the spawn telnet command. Try setting TERM=unknown. Otherwise look into the arguments that your telnet program supports to disable escape sequences.
Related
I'm facing a problem while trying to pass a variable value to a grep command.
In essence, I want to grep out the lines which match my pattern and the pattern is stored in a variable. I take in the input from the user, and parse through myfile and see if the pattern exists(no problem here).
If it exists I want to display the lines which have the pattern i.e grep it out.
My code:
if {$a==1} {
puts "serial number exists"
exec grep $sn myfile } else {
puts "serial number does not exist"}
My input: SN02
My result when I run grep in Shell terminal( grep "SN02" myfile):
serial number exists
SN02 xyz rtw 345
SN02 gfs rew 786
My result when I try to execute grep in Tcl script:
serial number exists
The lines which match the pattern are not displayed.
Your (horrible IMO) indentation is not actually the problem. The problem is that exec does not automatically print the output of the exec'ed command*.
You want puts [exec grep $sn myfile]
This is because the exec command is designed to allow the output to be captured in a variable (like set output [exec some command])
* in an interactive tclsh session, as a convenience, the result of commands is printed. Not so in a non-interactive script.
To follow up on the "horrible" comment, your original code has no visual cues about where the "true" block ends and where the "else" block begins. Due to Tcl's word-oriented nature, it pretty well mandates the one true brace style indentation style.
I have written an Expect script that logs into to a remote system, executes some commands in a sequence and captures the output in a log file.
Everything is happening fine except the fact that when I check the log file, some commands appear to be sent twice such that, the next command to be sent, appears in the middle of the output of the previous one. It is also sent again on detecting the prompt (which is the correct execution). Also, this issue does NOT occur in all cases, which is even more baffling.
I would like to add that I have customized the prompt to include this " ---> ". This is for easier output parsing by another script.
Here's the expect code,
set prompt "(]|%|#|>|\\$)"
# go to bash shell
expect -re $prompt
send "/bin/bash\r"
# customize the prompt
expect -re $prompt
send "PS1=\"\\u#\\H ---> \"\r"
# set new prompt into variable
expect -re $prompt
set newPrompt " ---> "
# opens file containing command list
set commFile [open commands.txt]
# reads each line containing commands from file, stores it in "$theLine" variable and sends it.
while {[gets $commFile theLine] >= 0} {
expect "$newPrompt"
send "$theLine\r"
}
close $commFile
This is how my output appears.
"prompt --->" command1
----output----
----output----
command2
----output----
----output----
"prompt --->" command2
----output----
----output----
Hope you get the idea.
I don't understand this behaviour nor was I able to find any solutions to this elsewhere. Any ideas?
There's a bit of a logic problem: after you send PS1=... you expect the old prompt. Then inside the loop you expect the new prompt before sending another command. Does this help?
send "PS1=\"\\u#\\H ---> \"\r"
set newPrompt { ---> $}
expect -re $newprompt
set commFile [open commands.txt]
while {[gets $commFile theLine] >= 0} {
send "$theLine\r"
expect -re "$newPrompt"
}
As i know, if we do for example "./program | grep someoutput", it greps after program process finished. Do you know, how do it by income?
The shell will spawn both processes at the same time and connect the output of the first to the input of the second. If you have two long-running processes then you'll see both in the process table. There's no intermediate step, no storage of data from the first program. It's a pipe, not a bucket.
Note - there may be some buffering involved.
You're wrong.
The pipe recieves data immediately, but of course writing to the pipe by the source process can block if the other end (the sink) is not reading the data out fast enough.
Of course, this doesn't necessarily mean that pipes are suitable for "hard real-time" use, but perhaps that's not what you meant.
Actually, grep can be used "in real time" since data passed through pipes are not buffered, so something like tail -f /var/log/messages | grep something will work.
If you're not getting the expected output, it's more likely that the preceding command is buffering its output. Take for instance the double grep:
tail -f /var/log/messages | grep something | grep another
The output won't appear immediately since grep will buffer its output when stdout is not connected to a terminal which means the second grep won't see any data until the buffer is flushed. Forcing the line-buffering mode solves this issue:
tail -f /var/log/messages | grep --line-buffered something | grep another
Depending on how buffering is done, it may be possible to modify the buffering mode of a command using stdbuf e.g:
stdbuf -oL ./program | grep something
All,
I want to execute a unix statement in expect script.The unix statement outputs rsize value for a process. I haven't programmed in expect before.
This is my code:
#!/usr/bin/expect
set some_host "some host"
set Mycmd "top -l 1 -stats pid,rsize,command | grep Process_Name| awk '{print \$2};'"
spawn telnet localhost $some_host
expect "login:"
send "myDevice\r"
expect "Password:"
send "$password\r"
expect "\$"
send "$Mycmd\r"
When I execute this, I don't get any output. What's the correct syntax to execute the unix statement? How do I get this to work so that I get the correct rsize value as the output?
Always a good idea to try to escape with ascii, try \0442 for \$2 or try something like \\$2
.Also you can debug the script to find why you have no output if you insert 'exp_internal 1' without quotes at the second line.
Is it possible to get the output without having to add the "interact" statement
Yes, it is. Other statements which wait for the output will also do; you could add e. g.
expect -re "\n\[0-9]+"
to the end of your script.
I have a java program in a UNIX environment which requires line buffered data to be passed into System.in.
Passing in keyboard input from the terminal is fine, however if I try to redirect the input from a file in a way such as:
java the_program < input.txt
the program will not execute properly.
In what ways can I have line buffered as opposed to block buffered data be passed into the program via stdin?
I have tried:
stdbuf -oL cat input.txt | java the_program
and
stdbuf -i0 java the_program < input.txt
as well as
grep --line-buffered . input.txt | java the_program
but have not had any luck.
Any ideas or suggestions?
Most of the problem is in the Java program - why/how does it need the input to be line-buffered? It should be designed to use the analogue of C's fgets() so that it just reads a line at a time. If there is no such analogue, then maybe you need to write a function/class that provides that service, taking whatever you can read in whatever units are provided, and either split or concatenate at line boundaries.
Failing that, you may have to indulge in unportable operations such as using the fstat() system call on the pipe file descriptor, only writing to the pipe when there is no data in it (looking at the st_size member). However, it is not guaranteed that it will work - unportable means it may not. Obviously, you'd ensure your program writes a line at a time and flushes the output if using standard I/O.