I am having an issue. I have a simple expect script that i call in a php script to login to a cisco terminal server to clear vty lines after a lab time is over. The logic is simple that if a user is present then it only occupies line vty 0.
The problem occurs if a user is not present... the cisco router just displays an error stating %connection to clear or something and expect run the rest of the script which is not necessary because i am managing a lab of 10 routers and loading configuration files which takes a lot of time.
Please tell me how to read the error from log and end script if i get that message.
#! /usr/bin/expect -f
spawn telnet 192.168.2.1
set user [lindex $argv 0]
set pass [lindex $argv 1]
expect "Username:"
send "$user\r"
expect "Password:"
send "$pass\r"
expect "*>"
send "enable\r"
expect "*#"
send "clear line vty 0\r"
send "\r"
expect "*#"
send "copy tftp://192.168.2.3 running-config\r"
send "config\r"
send "\r"
expect "*#\r\n"
The error handling code you are asking about is here...
send "clear line vty 0\r"
expect {
"confirm]" { send "\r" }
"% Not allowed" { send "quit\r"; exit }
}
expect "#"
This looks for either [confirm] or % Not allowed to clear current line and makes an appropriate go / no-go decision.
I made a few modifications to your script so I could run it against machines in my lab. I'm not sure how you disabled the router from asking for an enable password, but that may be something to add to your script.
If you wanted to make the script more robust, you could issue a show user before clearing lines, and only clear lines that your script isn't on. I will leave that as an exercise for you to experiment with.
#!/usr/bin/expect -f
spawn telnet 172.16.1.5
set user [lindex $argv 0]
set pass [lindex $argv 1]
expect "Username: "
send "$user\r"
expect "assword: "
send "$pass\r"
expect ">"
send "enable\r"
expect "assword: "
send "$pass\r"
expect "#"
send "clear line vty 0\r"
expect {
"confirm]" { send "\r" }
"% Not allowed" { send "quit\r"; exit }
}
expect "#"
send "copy tftp://192.168.2.3 running-config\r"
expect "Source filename *]? "
send "config\r"
expect "Destination filename *]? "
send "running\r"
expect "#"
exit
Related
Using GenericContainer#execInContainer I can only get stdout or stderr.
Is there any way to get exit code of executed command?
I can't rely on the presence of text in stderr. The application I execute prints some info to stderr but exits with code 0.
execInContainer is just a shortcut to execCreateCmd/execStartCmd from docker-java. Unfortunately, their API doesn't provide a way to get the exit code.
But you can make use of built-in shell functionality and just return the code as part of stdout/stderr:
$ sh -c 'false; echo "ExitCode=$?"'
ExitCode=1
where false is your command
You can use inspectExecCmd(execId) to get information about the executed command, and also you can get exit code from the response of inspectExecCmd
I have a Powershell script running which calls a function from a dot-sourced .ps1 file.
Inside this function I do an exit 1 which terminates the whole script (as intended).
When I now look at $? and $LASTEXITCODE it says True and 0.
Shouldn't there be False and 1?
Is there anything I don't see?
Example:
main script:
Log-Error -Error "some error" -exit $True
in function.ps1:
Function Log-Finish {
[CmdletBinding()]
Param ([Parameter(Mandatory=$false)][boolean]$Exit)
Process {
" error "
# If $Exit is $true, end calling script
If(($Exit) -or ($Exit -eq $True)) {
Exit 1
}
}
}
You will found an explanation to your "issue" in this post http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/12/powershell-error-handling-and-why-you-should-care.aspx
Also, remember that when external command or script is run, $? will
not always tell you a true story. Let’s see why. Create a script that
has nothing but one line—our favorite error generating command:
Get-Item afilethatdoesntexist.txt
Now run the script and see the output. You will notice that the host
shows you the error. You will also notice that $error contains the
error object that was generated by the command in the script. But $?
Is set to TRUE! Oh, and don’t try this in the order I mentioned
because it will skew the results of $?.
So can you tell me why $? Is set to True? Because your script ran
successfully as far as Windows PowerShell is concerned. Every step in
script was executed—whether it resulted in an error or not. And that
was successful in doing what the script told Windows PowerShell to do.
It doesn’t necessarily mean that the commands within script didn’t
generate any error. See how quickly it gets confusing? And we haven’t
started to go deep yet!
So I'm getting a strange issue when trying to send an email from my company's local mail server using Tcl. The problem is I've written code that works, but it doesn't work as soon as I wrap it with TclApp. I believe I've included all the necessary packages.
Code:
package require smtp;
package require mime;
package require tls;
set body "Hello World, I am sending an email! Hear me roar.";
#mime info
set token [mime::initialize -canonical text/plain -string $body];
#mail options
set opts {};
#MAIL SERVER + PORT
lappend opts -servers "my_server";
lappend opts -ports 25;
tls::init -tls1 1;
lappend opts -username "someEmail#example.com";
lappend opts -password "somePasswordExample";
#SUBJECT + FROM + TO
lappend opts -header [list "Subject" "This is a test e-mail, beware!!"];
lappend opts -header [list "From" "theFromEmail#example.com"];
lappend opts -header [list "To" "theToEmail#yahoo.com"];
if {[catch {
smtp::sendmessage $token \
{*}$opts \
-queue false \
-atleastone false \
-usetls false \
-debug 1;
mime::finalize $token;
} msg]} {
set out [open "error_log.txt" w];
puts $out $msg;
close $out;
}
puts "Hit enter to continue...";
gets stdin;
exit;
This works when I run it and I successfully get the email sent.
But when I wrap it, it doesn't. Here's the output after wrapping and executing the program:
For whatever reason, wrapping with TclApp makes my program fail to authenticate.
*Update: I've decided to try to wrap the script with Freewrap to see if I get the same problem and amazingly I do not. Script works if not wrapped or if wrapped by Freewrap, but not TclApp; is this a bug in TclApp or am I simply missing something obvious?
It seems that this is an old problem (last post): https://community.activestate.com/forum/wrapping-package-tls151
Investigate whether the wrapped version has the same .dll
dependencies as in the article you linked.
Check in the TCL Wiki to see whether this is a known issue ( TCL
Wiki ).
Are you initializing your environment properly when wrapped ( TCL
App Initialization )?
I've found the solution to my problem and solved it! Hopefully this answer will help anyone else who ran into the same issue.
I contacted ActiveState and they were able to point me in the right direction - this link to a thread on the ActiveState forums goes over a similar issue.
I've decided to run the prefix file I've been using to wrap my programs in TclApp - I am using base-tk8.6-thread-win32-ix86. Running this opens up a console/Tcl interpreter which allowed me to try sourcing my Tcl e-mail script manually and I found that the prefix file/interpreter by itself was completely unaware of the location of any package on my system and that I needed to lappend to the auto_path the location of the packages I wanted. Moreover I found from the thread that the email script I was using required other dependencies I had not wrapped in. Namely sha1, SASL, and otp among their own dependencies. When I got these dependencies my script worked through the base-tk8.6-thread-win32-ix86 interpreter and subsequantly through my wrapped program.
Another clue that these dependencies were necessary after doing some research was that my script would give me a 530: 5.5.1 Authentication Required. I later learned SASL fixed this - but I don't know anything about networking so I wouldn't have guessed it.
The other thing I learned was there is a distinct difference between teacup get and teacup install which is why I wasn't installing Tcl packages correctly and TclApp was unaware of SASL, sha1, or otp.
What I don't understand, and perhaps someone with more in depth knowledge about these programs can tell me, how does Wish86 know about a script's package dependencies and know where to find them?? It wasn't until I tried looking for the packages in TclApp that I realized I didn't even have sha1, SASL, etc. on my system nor did I included their package require commands at the top of my script, yet Wish86 could execute my script perfectly. The frustrating thing about this is it is difficult to know whether or not you've met all dependency requirements for systems that don't have a magical Wish86 interpreter that just makes everything work (lol.)
After looking through the end of the thread, I found there is a discussion on the depth TclApp goes to look for hard and soft dependencies in projects.
EDIT: Added more information.
I have a expect script which does the following:
Spawns a.sh -> a.sh waits for user input
Spawns b.sh -> runs and finishes
I now want to send input to a.sh but having difficulties getting this working.
Below is my expect script
#!/usr/bin/expect
spawn "./a.sh"
set a $spawn_id
expect "enter"
spawn "./b.sh"
expect eof
send -i $a "test\r"
a.sh is
read -p "enter " group
echo $group
echo $group to file > file.txt
and b.sh is
echo i am b
sleep 5
echo xx
Basically, expect will work with two feasible commands such as send and expect. In this case, if send is used, then it is mandatory to have expect (in most of the cases) afterwards. (while the vice-versa is not required to be mandatory)
This is because without that we will be missing out what is happening in the spawned process as expect will assume that you simply need to send one string value and not expecting anything else from the session.
After the following code
send "ian\n"
we have to make the expect to wait for something afterwards. You have used expect eof for the spawned process a.sh . In a same way, it can be added for the b.sh spawned process as well.
"Well, then why interact worked ?". I heard you.
They both work in the same manner except that interact will expect some input from the user as an interactive session. It obviously expect from you. But, your current shell script is not designed to get input and it will eventually quit since there is no much further code in the script and which is why you are seeing the proper output. Or, even having an expect code alone (even without eof) can do the trick.
Have a look at the expect's man page to know more.
I've just got this working using
spawn "./a.sh"
set a $spawn_id
expect "enter"
spawn "./b.sh"
expect eof
set spawn_id $a
send "ian\n"
interact
My question now is why do you need interact at the end?
It's not clear to me if send_user is the same as puts. Every time I want to send an informative message to the user, I would wonder which one I should use. From Expect's man page, it seems like send_user is the same as puts but then what is send_user used for?
Another difference I just discovered between the two, apart from the newline thing, is that if you're using log_file in your Expect script, statements sent via send_user will make it into the logfile, whereas statements sent with puts do not. If you're automating some Expect scripts which aren't being run on your actual console, that can make a big difference.
The main difference is that puts automatically appends a newline and
send_user does not. In this regard, puts -nonewline is more analagous
to send_user.
send_user also "inherits" some options from expect's send, such as -s
and -h (check the expect man page for details). See
http://99-bottles-of-beer.net/language-expect-249.html
for a usage of the -h flag.
I cannot speak to how they're implemented at the C-level.