I have written an expect script which I am calling from my bash script, which removes the content in the directories, copies the jar and extracts it. I am doing it through expect script shown below:
I have used sleep and wait between the process and nothing helps. I do not get the desired output as expected. Please check the script is fairly simple, it removes content inside the directory, created one, add jar and tries to extract it.
set timeout -1
set PASS [lindex $argv 0];
set DIRECTORY [lindex $argv 1];
set FOLDER_NAME [lindex $argv 2];
set WAR_PATH [lindex $argv 3];
set WAR_NAME [lindex $argv 4];
spawn sudo rm -rf $DIRECTORY/$FOLDER_NAME
expect "Password:"
send $PASS\r
spawn sudo mkdir $DIRECTORY/$FOLDER_NAME
expect "Password:"
send $PASS\r
spawn sudo cp $WAR_PATH $DIRECTORY/$FOLDER_NAME
expect "Password:"
send $PASS\r
spawn sudo jar -xf $DIRECTORY/$FOLDER_NAME/$WAR_NAME
expect "Password:"
send $PASS\r
set timeout -1
expect eof
exit 0
Please help me so that this process is completed one after another without any problem. Thanks for your help.
After each send $PASS\r, you should expect eof to wait for the spawned process to complete.
Related
This question already has an answer here:
Parsing command line using argc and argv in expect
(1 answer)
Closed 3 years ago.
I would like to remove all log files inside directory /var/log/$some_project/
I can remove them using shell command :
sudo rm /var/log/$some_project/*.log
But I have created expect script as shown below. Where I pass the PASS (my system password) and FILES (/var/log/$some_project/*.log) but it does not delete the files. It deleted only one file the first one.
I also tried instead of passing FILES/*.log, I just passed /var/log/$some_project and use the second script. But still, I am not able to remove all the log files.
I have also tried passing each file to expect script and remove still it does not work.
First Script
set timeout -1
set PASS [lindex $argv 0];
set FILES [lindex $argv 1];
spawn sudo rm $FILES
expect "Password:"
send $PASS\r
set timeout -1
exit 0
expect eof
Second Script
set timeout -1
set PASS [lindex $argv 0];
set FILES [lindex $argv 1];
spawn sudo rm $FILES/*.log
expect "Password:"
send $PASS\r
set timeout -1
exit 0
expect eof
Please, I would want to expect to understand the wildcard character and remove the files from the directory specified.
If you pass a wildcard expression to a script, the shell in which you run the script expands the wildcard before starting the script. So by the time Expect runs, [lindex $argv 1] really contains only the first one of the files you want to removed
I want to remotely delete a file/execute another script on my server. Manually this could be done by ssh-login -> cd /path/ -> rm somefiles -> . script.sh
I want to automatic this process. So that when I execute expect expectscript.sh port serverip user userpasswd, the script would do the whole process for me.
So I write the following script. Things go smoothly till the ssh-login process finished. I don't know what is wrong with the last 3 lines of the code. Could someone help?
#!/usr/bin/expect
set timeout 20
set port [lindex $argv 0]
set ip [lindex $argv 1]
set user [lindex $argv 2]
set password [lindex $argv 3]
spawn ssh "$user\#$ip" "-p" "$port"
expect "password:"
send "$password\r"
spawn "cd /etc/abcd/"
spawn "rm -f efg/*"
spawn ". somescriptinefg.sh"
Change the spawn to send solve the problem~
Literally,
spawn "Creates a new process by running a given program."
send "Sends string to the current process."
The problem seems to be that the password is being sent with a spawn command rather than a send command. Additionally, ssh can be called with a specific command to run during the session, for example:
#!/usr/bin/expect
set timeout 20
set port [lindex $argv 0]
set ip [lindex $argv 1]
set user [lindex $argv 2]
set password [lindex $argv 3]
spawn ssh $user#$ip -p $port "cd /etc/abcd/; rm -f efg/*; . somescriptinefg.sh"
expect "password:*"
send "$password\r"
expect eof
It might be worth configuring ssh keys for passwordless access instead. This would eliminate the need for an expect script and reduce the whole thing to a single line. If you really need to have an interactive ssh session, then a tool such as sshpass could be a less impractical alternative.
I'm working on a small script to try and automate the installation of pear on a system should it be missing - basically, taking the interactive portions of the installation process and making them non-interactive so all I need to do is execute the script and it does it for me on its own. This is my first time trying to use expect and it's, well, not what I expected.
Sample code below:
/usr/bin/expect <<EOD
set timeout 20
set number [lindex $argv 0]
set path [lindex $argv 1]
spawn php -q go-pear.phar
expect "1-11, 'all' or Enter to continue:"
send "$number\r"
interact
expect "Installation base ($prefix) [/usr/local] :"
send "$path\r"
interact
EOD
This is not quite working at the moment as it's trying to fill in the /usr/local portion in the first menu as follows:
1-11, 'all' or Enter to continue: invalid command name "/usr/local"
while executing
"/usr/local"
invoked from within
"expect "Installation base () [/usr/local] :""
Can anyone show me what I'm missing here? Also, I'd like to get this so I don't have to run it as ./script $var0 $var1 but rather just run it as ./script with everything being contained within and filled in, but not sure how to do that.
Thanks in advance for any help you can offer.
One problem is that the [...] inside the string tells expect to execute a command. I think you need to escape them with \[...\].
Hope this helps a little =)
I ended up figuring this out. In case anyone else wants to do something similar, here's what worked for me:
/usr/bin/expect <<EOF
set send_slow {1 .1}
set timeout -1
spawn php -q go-pear.phar
expect "1-11, 'all' or Enter to continue:"
sleep .1
send -s -- "1\r"
expect -exact "1\r"
sleep .1
send -s -- "/usr/local\r"
expect -exact "/usr/local\r"
expect "1-11, 'all' or Enter to continue:"
sleep .1
send -s -- "\r"
expect -exact "\r"
expect EOF
I am writing a Bash script and using Expect to do sftp. Now in the Expect block I want to access a Bash variable in a conditional statement. But, I am unable to do so. How can do this?
Also, the execution of this script is controlled from a C program and I want redirect the output to a log file (which again is dynamic). Can I do that and suppress all the output on standard output.
Here is the code:
!/usr/bin/bash
host=$1
user=$2
pass=$3
action=$4
path=$5
echo "Starting...."
function doAction {
strAction="\""$action"\""
echo $strAction
/usr/bin/expect <<EOF > logfile.txt
**set bashaction $strAction**
spawn sftp $user#$host
expect "password:"
send "$pass\r"
expect"sftp>"
send "cd $path\r"
**if {$bashaction == "TEST"} {**
expect "sftp>"
send "prompt\r"
}
expect "sftp>"
send <sftp command>
expect "sftp>"
send_user "quit\n"
exit
EOF
}
doAction
echo "DONE....."
For 1. using an Expect script instead worked.
For the logging issue, using log_user 0 and log_file -a <file> helped.
You don't need to use Bash. Expect can handle all that:
#!/usr/bin/expect
set host [lindex $argv 0]
set user [lindex $argv 1]
set pass [lindex $argv 2]
set action [lindex $argv 3]
set path [lindex $argv 4]
puts "Starting...."
puts "\"$action\""
spawn sftp $user#$host
expect "password:"
send "$pass\r"
expect"sftp>"
send "cd $path\r"
if {$action == "TEST"} {
# Do something
} else {
# Do something else
}
expect "sftp>"
send_user "quit\r"
puts "DONE....."
Coming from Bash, the Tcl/Expect syntax is a little strange, but you should not have any problem expanding the above skeleton.
Accessing Environment Variables from TCL and Expect
Since you are calling this Expect script from another process, you can make use of environment variables. For example, if your parent process has exported action to the environment, then you can access its value within your expect script with:
$::env(action)
In Bash, you can mark the variable for export with the export builtin. For example:
export action
Since I'm not sure how you're invoking the Expect script from C, it's up to you to make sure the variable is properly exported.
Disable Logging to Standard Output
To disable logging to standard output from spawned processes, Expect provides the log_user command. You can prevent your spawned processes from writing to stdout with log_user 0.
The expect(1) manual says:
By default, the send/expect dialogue is logged to stdout (and a
logfile if open). The logging to stdout is disabled by the command
"log_user 0" and reenabled by "log_user 1". Logging to the logfile
is unchanged.
This doesn't actually close standard output, which is generally not what you want anyway. Doing so will cause anything that writes to stdout to throw an error like this:
can not find channel named "stdout"
while executing
"puts hello"
(file "/tmp/foo" line 8)
To suppress output to the standard output you can use
command here >/dev/null 2>/dev/null
To write to a log file, you can use similar piping (> or >>), or the tee command if you want to write the output in the middle of a long pipe.
I have a script(dobrt) which upon executing asks for a password.How can i write a script which executes dobrt and automatically supplies the password it asks for.
when i execute ./dobrt -p file.txt , the system asks for a password. I want the password to be sent in automatically by the script. Here is the output
$ ./dobrt -p file.txt
Found 194 tests to execute
------------ 2010 February 11 11:27:33 ------------
Password: ***************
I tried using shell and expecxt scripts for this. here is what i did.
I have 2 scripts. I call the second script(run_dobrt.exp) from the first one(run_dobrt.sh).
Script 1 : run_dobrt.sh
#!/bin/ksh
TESTCASE_HOME="/home/abhijeet/code/testcases";
TESTCASE_LIST="file.txt";
PASSWORD="*****";
echo "Running Expect Script"
`./run_dobrt.exp $TESTCASE_HOME $TESTCASE_LIST $PASSWORD`
Script 2: run_dobrt.exp
#!/usr/local/bin/expect -f
set TESTCASE_HOME [lindex $argv 0];
set TESTCASE_LIST [lindex $argv 1];
set PASSWORD [lindex $argv 3];
set timeout 200
spawn $TESTCASE_HOME/dobrt -p $TESTCASE_HOME/$TESTCASE_LIST
expect "*?assword:*" {send -- "$PASSWORD\r";}
expect eof
Now when i run run_dobrt.sh i get the following error
run_dobrt.sh[20]: spawn: not found
How to get rid of this error and get this task done? Please help.
What is dobrt? is a self-made program? If this is the case I think you will have to recode it to parse an extra argument that accepts the password. Then you will be able to pass this passowrd to dobrt just as you do it like "-p file.txt" in the command line (through a script).
I see two problems:
In the last line of your shell script, remove the back-quotes `` around the command,
they will cause the output of the expect script to be executed as a shell command.
In the expect script, change
set PASSWORD [lindex $argv 3];
to
set PASSWORD [lindex $argv 2];
you are skipping an argument.
If the password is the only input dobrt prompts for, you could try this:
Script 1 : run_dobrt.sh
#!/bin/ksh
TESTCASE_HOME="/home/abhijeet/code/testcases";
TESTCASE_LIST="file.txt";
PASSWORD="*****";
./run_dobrt.exp $TESTCASE_HOME $TESTCASE_LIST << EOF
$PASSWORD
EOF