How to put sleep command in a tcl script? - tcl

I'm trying to put a sleep command in a tcl script to wait 10 seconds before send the disconnect command:
#!/usr/bin/expect -f
set n 0
if { $argc != 1 } {
puts "The script requires the number of bot."
puts "Please try again."
exit 1
} else {
set n [lindex $argv 0]
}
# Spawn Python and await prompt
spawn mono --debug pCampBot.exe -loginuri http://127.0.0.1:9000 -s home -n $n -firstname test -lastname bot_ -password 123 -b p
expect "pCampbot#"
# Send Python statement and await prompt
send "conn\n"
expect "pCampbot#"
sleep 10
send "disconn\n"
expect "pCampbot#"
# Pass control to user so he can interact with Python
interact
The problem is that sleep command it's like it's executed after the spawn command, that is it waits 10 seconds and after send "conn" and "disconn" commands sequentially.
I don't know why it behaves like that and i don't know how i can solve this problem.

Tcl uses the after command for this, provided you give it a single argument that is an integer number of milliseconds. To sleep for 10 seconds, you do:
after 10000

Related

Expect script should not end

I need some help with my script. I have written a piece of code where the script uses ssh to remote host and executes a tail command and need to stay there. It should not come out of the script.
#!/usr/bin/tclsh
package require Expect
set IP [lindex $argv 0]
set spawnID [spawn ssh root#$IP]
expect {
password: {
send "XXXXXXX\r"
exp_continue
}
"# "
}
send "kubectl -it exec server-0 bash\r"
expect "# "
send "tail -f Server.log\r"
expect "$"
The tail -f command should stay but its coming out of the script in few seconds.
Its printing the logs as expected but comes out of the session in 10 seconds.
Requirement is to stay there unless the user hits "ctrl c"

Exit #!/usr/bin/expect when Status was VPN tunnel closed

i am using an expect script
#!/usr/bin/expect -f
set force_conservative 0 ;
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn $env(SHELL)
match_max 100000
send -- "cd /home/forticlientsslvpn/64bit/\r"
send -- "./forticlientsslvpn --server ip:port --vpnuser UN"
expect -exact "./forticlientsslvpn --server ip:PORT --vpnuser UN"
send -- "\r"
expect -exact "\r
Password for VPN:"
send -- "PW\r"
expect -exact "\r
STATUS::Setting up the tunnel\r
STATUS::Connecting...\r"
send -- "Y\r"
expect eof
file which will connect VPN,
when VPN connection is successful it will display STATUS::Tunnel running,
But when connection closed, STATUS will be Tunnel closed and still the script will keep on running
STATUS::Stopping tunnel
STATUS::Tunnel closed...```
How to exit the script when we get ```STATUS::Tunnel closed```
The problem is that you spawn a shell, and when the vpn client closes, the shell is still running.
Spawn the vpn client directly:
#!/usr/bin/expect -f
set timeout -1
cd /home/forticlientsslvpn/64bit
spawn ./forticlientsslvpn --server ip:port --vpnuser UN
match_max 100000
expect "Password for VPN:"
send -- "PW\r"
expect "STATUS::Connecting..."
send -- "Y\r"
expect eof
By adding expect Stopping and expect closed in the last lines of the script will exit the script.
expect Stopping
expect closed
exit

Catch an error in piped MySQL command (bash)

Is there any way to avoid the first eval for code below? I tried to play with ${LASTPIPE[0]} and such things but it was way too complicated for me. For instance when I tried to inject code with semicolon ($MYSQLCOMMAND; if ...) it broke my output to the pipe. I spent more than 8 hours wandering StackOverflow just to give up and write one more SQL command without pipe. Don't want to publish bad written code.
MYSQLQUERY="select * from $TABLENAME"
MYSQLTOPTIONS="--defaults-extra-file=$EXTRA -h $HOSTNAME -D $DBNAME -N -e"
MYSQLCOMMAND='mysql $MYSQLTOPTIONS "$MYSQLQUERY"'
# Exit immediately if something wrong with MySQL command
if eval "$MYSQLCOMMAND > /dev/null" ; then : ; else \
printf "Script returned non-zero exit code: %s\n" "$?" ; exit $?; fi
# Count rows for valid JSON output
ROWS=0
eval $MYSQLCOMMAND | \
while read ; \
do
((ROWS++))
done
(rest of the code generates JSON with calling the same
eval ... while read... and verified by https://jsonlint.com/)
Also I'd like to hear any your comment on the code since I'm not an experienced bash coder.

Expect Tcl script - Error passing quoted argument using spawn

I just wrote a very simple Expect script for wrapping around rsync, but it seems to be giving me trouble. Basically, I am automating the SSH login prompt called from rsync. I also have to pass arguments through rsync to SSH so it doesn't do the host key checking. I am well aware of SSH authentication keys and ssh-keygen, but I have good reasons for doing things this way so no lectures on passing passwords on the command-line.
Script
#!/usr/local/bin/expect -f
if {$argc != 5} {
puts "usage: remoteCopy {remotehost, username, password, localfile, remoteloc}"
exit 1
}
set remotehost [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set localfile [lindex $argv 3]
set remoteloc [lindex $argv 4]
set timeout -1
spawn rsync -e \"ssh -q -o StrictHostKeyChecking=no\" $localfile $username#$remotehost:$remoteloc
expect "Password"; send "$password\r"
Here is the complete output from the script:
Output
avoelker#localhost $ ./remoteFileCopy.tcl remotehost remoteuser remotepass ~/localfile /tmp/
spawn rsync -e "ssh -q -o StrictHostKeyChecking=no" /localhost/home/avoelker/localfile remoteuser#remotehost:/tmp/
rsync: Failed to exec "ssh: No such file or directory (2)
rsync error: error in IPC code (code 14) at pipe.c(83)
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(434)
send: spawn id exp6 not open
while executing
"send "$password\r""
(file "./remoteFileCopy.tcl" line 17)
avoelker#localhost $
It appears to me that rsync is trying to execute "ssh instead of just ssh, however, copying and pasting the first line of output from Expect's stdout (rsync -e "ssh -q -o StrictHostKeyChecking=no" /localhost/home/avoelker/localfile remoteuser#remotehost:/tmp/) directly into the shell works perfectly fine, so I know it isn't a problem with rsync.
When I remove the -e argument entirely from the spawn rsync line, the Expect script executes without errors, but I would have to add in host key checking to the script, which I do not want to do.
Does someone more experienced with Expect/Tcl know what I am doing wrong?
Drop your backslashes. The spawn line should just say:
spawn rsync -e "ssh -q -o StrictHostKeyChecking=no" $localfile $username#$remotehost:$remoteloc
After all, you don't want rsync to see a command with a quote in it, do you?

could not able to spawn(ssh) using expect

while executing
$expect filename.exp user pwd ip
I got the error
could not execute "ssh -l user ip": no such file or directory
The contents of filename.exp are this:
#!/opt/sfw/bin/expect -D
set OMC_Usr [lindex $argv 0]
set OMC_Pwd [lindex $argv 1]
set OMC_IP [lindex $argv 2]
set cmd "ssh -l $OMC_Usr $OMC_IP"
spawn $cmd
expect "Password:"
send "$OMC_Pwd\r"
interact
help me to proceed
Thanks...
The problem is that spawn needs the command and its arguments passed to it as multiple Tcl arguments, just like the standard Tcl exec command. The fix is to do this directly:
spawn ssh -l $OMC_Usr $OMC_IP
Or, if you prefer (and you've got Tcl 8.5):
set cmd "ssh -l $OMC_Usr $OMC_IP"
spawn {*}$cmd
Or, if you've got 8.4 or before:
eval spawn [lrange $cmd 0 end]
But don't do this:
eval spawn $cmd
because that will break unexpectedly if you have a Tcl metacharacter in the username (or IP address, but that's very unlikely).
Of course, the real fix is to set up an RSA keypair and use ssh-agent to manage it. Like that, you won't need to pass passwords on any command line; that's important because the command line of a process is public information about the process. Really. You can find it out with something trivial like ps -efww (or the equivalent for your OS). Environment variables are just as insecure too; there's an option to ps to show them too.