using command line argument while using expect - scripting

Hi I am using expect to mput a file to a remote machine.I am passing the filename as a command line argument to the script.But error is throwing from the line
send -- "mput $1\r"
My code is as follows:
set timeout 1000
spawn ftp $ipaddress
expect "Name "
send -- "$username\r"
expect "Password"
send -- "$passwd\r"
expect "ftp>"
send -- "mput $1\r"//error thrown from this line
expect "mput $1? "
send -- "y\r"
expect "ftp>"
send -- "bye\r"
Could anyone please suggest what is wrong here?

Replace $1 with [lindex $argv 0]. The $argc variable tells the number of given arguments.

Related

redirecting sql output to a file in a shell script

I am facing an issue while executing the following script snippet.
$ORACLEHOME/bin/sqlplus -s $DBUSER/$DBPASSWORD <<EOF
set pages 0 feedback off
SELECT * FROM ERR_STG_ROAMING_PARTNER;
EOF > Err_File.txt
The following error message appears.
./Roaming.sh: line 213: warning: here-document at line 206 delimited by end-of-file (wanted `EOF')
./Roaming.sh: line 214: syntax error: unexpected end of file
Any help will be appreciated.
Try this:
$ORACLEHOME/bin/sqlplus -s $DBUSER/$DBPASSWORD > Err_File.txt <<EOF
set pages 0 feedback off
SELECT * FROM ERR_STG_ROAMING_PARTNER;
EOF
That is, specify the output redirection before the input heredoc redirection. The shell expects EOF to be on its own on the line terminating the heredoc.
The error message you are getting is the shell complaining about finding end-of-file (of the script file) before finding EOF. The usage of EOF for the heredoc delimiter might lead to some confusion here!

Expect - Use default variable if no argument is specified

I've searched on stackoverflow and haven't really found an answer to this.
I'm pretty new to scripting and I have created a fully functional Expect script but I would like to improve it a bit. Currently I have created 3 lindex values of argv 0, 1 and 2 for hostaddress, username and password.
I would like to create a default username and password if argv 1 and 2 is NOT specified. I tried solving this through some if statements but after searching through stackoverflow it seems that TCL/Expect does not support NULL or empty values. Instead you have to make a query for it. Currently my code looks like this:
#!/usr/bin/expect
#Variables
set HOSTADDRESS [lindex $argv 0]
set USER [lindex $argv 1]
set PASSWORD [lindex $argv 2]
spawn ssh $USER#$HOSTADDRESS
set timeout 100
expect {
"(yes/no)?" {send "yes\n"; exp_continue}
"assword:" {send "$PASSWORD\n"}
}
expect {
"%" {send "cli\r"; exp_continue}
">" {sleep 1}
}
send "show interfaces st0 terse | match st0. | count \r"
expect "Count:???"
puts [open $HOSTADDRESS.op5.vpn.results w] $expect_out(0,string)
expect ">"
send "exit\r"
expect {
"%" {send "exit\r"; exp_continue}
"closed." {exit}
}
exit
Can you guys please help me create a default variable for $USER and $PASSWORD if it's not specified in the argv 1 or argv2?
Tcl doesn't support NULL at all. Or rather, it actually maps it to the variable being unset (that's exactly what happens with local variables under the hood; global variables are different). To query whether a variable exists, you use info exists (and yes, that's actually a NULL check in its implementation).
However, for handling defaulting of values from users on the command line, it is better to do it like this:
proc parseArgv {hostAddress {user "TheDefaultUser"} {pass "TheDefaultPassword"}} {
variable ::HOSTADDRESS $hostAddress
variable ::USER $user
variable ::PASSWORD $pass
}
parseArgv {*}$argv
If you're using 8.4 (upgrade, man!) then replace that last line with:
eval parseArgv $argv
You could also do it by looking at the llength of $argv (or the value in $argc) and doing conditional stuff based on that, but leveraging Tcl's proc default argument value stuff is easier (and you even get a reasonable error when someone gives too few or too many arguments).

hide error messages in dcl script

I have a test script I'm running that generates some errors,shown below, I expect these errors. Is there anyway I can prevent them from showing on the screen however? I use the
$ write sys$output
to display if there is an expected error.
I tried to use
$ DEFINE SYS$ERROR ERROR.LOG
but this then changed my entire error output log to this, if this is the correct way to handle it can I unset this at the end of my script somehow?
[error example]
%DCL-E-OPENIN, error opening TEST$DISK:[AAA]NOTTHERE.TXT; as input
-RMS-E-FNF, file not found
%DCL-E-OPENIN, error opening TEST$DISK:[AAA]NOTTHERE.TXT; as input
-RMS-E-FNF, file not found
%DCL-W-UNDFIL, file has not been opened by DCL - check logical name
DEFINE/USER creates a logical name that disappears when the next image exits.
So if you use that just before a command just to protect that command, then fine.
Otherwise I would prefer SET MESSAGE to control the output.
And of course yoy want to grab $STATUS and verify it after the command for success or for the expected error, reporting any unexpected error.
Better still... if you expect certain error conditions to occur,
then why not test for them?
For example:
$ file = F$SEARCH("TEST$DISK:[AAA]NOTTHERE.TXT")
$ IF file.NES."" THEN TYPE 'file'
Cheers,
Hein
To suppress Error message inside a script. try this command
$ DEFINE/USER SYS$ERROR NL:
NL: is a null device, so you don`t see any error messages displayed on your terminal.
good luck
This works interactively and in batch.
$ SET MESSAGE /NOTEXT /NOSEV /NOFAC /NOID
$ <DCL_Command>
$ SET MESSAGE /TEXT /SEV /FAC/ ID

connecting to switch via ssh using expect

I'm trying to run an script to connect to a Procurve 4204vl switch using expect.
This is the code I created:
#!/usr/bin/expect -f
set timeout 20
spawn ssh -l user 192.168.0.10
expect "user#192.168.0.10's password:"
send "1234"
send "\r"
expect "Press any key to continue"
send "j\r"
send "conf"
send "\r"
send "no ip route 89.19.238.2 255.255.255.255 192.168.0.12"
send "\r"
send "exit"
send "\r"
send "exit"
send "\r"
send "exit"
send "\r"
expect "Do you want to log out [y/n]?"
send "y"
I run this using simply expect script.exp, and the problem is I got these errors:
the route is not deleted
I got the following error on screen after the script execution is finished:
Press any key to continue invalid command name "y/n"
while executing
"y/n"
invoked from within
"expect "Do you want to log out [y/n]?""
(file "script.exp" line 19)
So, how could I solve this problem?
Thank you.
PS: if I comment all the "exit" lines and also the log out question, then add a last line with the "interact" command, the script works fine.
For route not deleted, what output is the program giving you? Do you see any errors from the router?
In expect and Tcl the square brackets are the syntax to execute a command, quite like backticks in the shell. The simplest solution is to use braces instead of double quotes to prevent command interpolation:
expect {Do you want to log out [y/n]?}
Braces act like single quotes in the shell.
send "logout\r"
expect {
"Do you want to log out" {
send "yy"
exp_continue
} "Do you want to save current configuration" {
set result $expect_out(0,string);
puts "save..."
send "y"
puts "ok"
} eof {
puts "end of script"
}
}
What it worked for me is to use regex (-re argument) and avoid using the characters [] in the expression:
expect -re "Do you want to log out"
It's also useful because if the output from the command is too long or dynamic, using static expression is limited.

How to get SQLCMD to output errors and warnings only

How can you get SQLCMD, when executing a SQL script file, to just output any errors or warnings it encounters?
I essentially dont want information based messages to be output.
It's not possible to prevent SQLCMD returning non-error output messages by passing it a parameter.
However, what you can do is redirect error messages to STDERR, then direct all other messages to NUL.
This is done by passing the -r parameter. From books online:
-r[ 0 | 1] msgs to stderr
Redirects the error message output to the screen (stderr). If you do not specify a parameter or if you specify 0, only error messages that have a severity level of 11 or higher are redirected. If you specify 1, all error message output including PRINT is redirected. Has no effect if you use -o. By default, messages are sent to stdout.
Set -r depending on exactly which error messages you want to display, but to display all error message output, an example command would be:
sqlcmd -Q "select 1 as a; select 1/0 as b" -E -r1 1> NUL
Just as an addition to this, if you are sending errors out to file, I found this https://www.simple-talk.com/sql/sql-tools/the-sqlcmd-workbench/
which I have used. If you omit setting the OUT, then you only get an error log created.
So you have a command like this :
sqlcmd -x -E -S MyServer -i C:\MySQLBatchToRun.sql
Then in MySQLBatchToRun.sql , something like this
USE MyDatabase
:Error C:\MyErrorLog.txt
:r C:\MySQLScript.sql
GO
In MySQLScript.sql you have the actual SQL to run. It's a bit convoluted, but works. The only issue I have is that it seems to create an empty error log file, even if there is not an error.
It looks like print statements are sent to stderr with -r1 so you can use them to log separate from your output like so:
sqlcmd -Q "print 'hello logfile';select 'Ted' as bro" -r1 1> C:\output.txt 2> C:\logfile.txt
This also works with -i inputfile like:
sqlcmd -i helloTed.sql -r1 1> C:\output.txt 2> C:\logfile.txt
helloTed.sql:
print 'hello logfile';
select 'Ted' as bro
Probably you could use -Q and insert exec a stored proc that contains prints.