Answer prompts in bash - bash

I am often in the need of running a bash script that needs inputs from me and im trying to improve my workflow by automating this.
In my case my bash script is in need of 3 inputs from me:
What interface should i use?
1
Enter the password:
mypass
Please restart the program:
sudo bash restart
How can i make my bash script file auto input theses values? I have tried figuring this out but all the answer are about inputing yes or no.

If that is all the input your program needs, then you can simply put the inputs, one per line, in a text file, then run it like this:
$> ./yourscript.sh < yourtextfile.txt
For your example, the text file would contain
1
mypass
sudo bash restart

If you have such a script.sh:
#!/bin/bash
read -p "What intergace should i use?"$'\n' interfacenum
echo
read -p "Enter the password:"$'\n' pass
echo
read -p "Please restaart the program:"$'\n' prog
echo
echo "Values:"
for i in interfacenum pass prog; do
echo $'\t'"$i=\"${!i}\""
done
You can 'input' the values into the script using echo or printf:
echo -ne "1\nmypass\nsudo bash restart\n" | ./script.sh

You can use expect and autoexpect to achieve your task.
Let's say this is your file:
cat hello.sh
#!/usr/local/bin/bash
read -p "Select the interface: " interface
echo "interface selected: $interface"
read -p "Enter the username: " username
echo "username: $username"
You don't have to even write the scripts. You can you autoexpect to generate the script for you.
autoexpect ./hello.sh
autoexpect started, file is script.exp
Select the interface: 1
interface selected: 1
...(more input and output to generate the script)
Examine the generated script.
tail -n7 script.exp
expect -exact "Select the interface: "
send -- "1\r"
expect -exact "1\r
interface selected: 1\r
Enter the username: "
send -- "vivek\r"
expect eof
Now sit back and run the generated script
./script.exp
spawn ./hello.sh
Select the interface: 1
interface selected: 1
Enter the username: vivek
username: vivek

Related

WIN10 openssh in cmd "ssh xxx#xxx.xxx.xxx.xxx sh xxx.sh" error ,cant read variable normaly

Im Win10 and installed the Openssh. My router is running Openwrt.The code is write via BASH
!!!The code is here!!!
flag1=1
option1_1="Its num1"
while [[ "$flag1" = "1" ]];do
read -n 1 -p "Please input num1 :" input1
case ${input1} in
1)
echo .
read -n 1 -p "Your input is: $input1,comfirm?[1/0]" comfirm1
if [[ "$comfirm1" = "1" ]];then
echo .
echo Your input is $input1,Goodbye
flag1=0
fi
;;
*)
echo Its not num1 ,please input again
flag1=1
;;
esac
done
There is a .sh file in my router and i need to run it through the steps follow:
Steps:
Win+R to open cmd.exe
type this command : ssh example#192.168.1.1 sh example.sh
And here the problem comes : it can't read the variable normally and cant output the words that i write in the file.
BUT,if i run this script use the command below,it would work normally:
Steps:
Win+R to open cmd.exe
type : ssh example#192.168.1.1
type : sh example.sh
Problems: (i have upload the video to Youtube :https://youtu.be/TPE9CjUQvxo)
It should read twich "1" and save to $input1 and $comfirm1,but it actually only read correctly when i type "11",other input will cause it loop forever.
I have noticed something , but i dont know what can do:
The things that i noticed:
When i use one command "ssh xxx#xxx.xxx.xxx.xxx sh xxx.sh",the cmd.exe window's title is still "C:\Winodws\system32\cmd.exe -ssh xxx#xxx.xxx.xxx.xxx sh test.sh".BUT when i break this command to two commands ,it change to "OpenSSH SSH client"
When i use one command,the code read -n 1 -p "xxx" wont work.it cant show the -p words or read only 1 character.
Anyone knows whats wrong and give me a advice to fix this ??

Expect: how to spawn a command containing a backslash?

I have the following script:
#!/bin/bash
echo -n "Enter user name: "
read USER
echo -n "Enter password: "
read -s PWD
cat $HOME/etc/switches.txt | while read IP SWITCH
do
echo ${SWITCH}
/usr/bin/expect <<EOD
# Change to 1 to Log to STDOUT
log_user 1
# Change to 1 to enable verbose debugging
exp_internal 1
# Set timeout for the script
set timeout 20
spawn ssh -l {$USER} -oCheckHostIP=no -oStrictHostKeyChecking=no -q $IP
match_max [expr 32 * 1024]
expect "Password:"
send $PWD
send "\n"
expect "#"
send "show fcip summary | grep TRNK\n"
EOD
echo
done
When I run it, the backslash in the username disappears, giving these result:
Enter user name: corp\user
Enter password:
=== ss3303-m-esannw-m01a ===
spawn ssh -l corpuser -oCheckHostIP=no -oStrictHostKeyChecking=no -q 10.247.184.70
[...]
I suspect my problem is due in part to embedding my expect script inside a bash script. I've tried using $USER and "$USER" as well, with the same results. Using corp\\\\user (yes, four backslashes!) does work but is inconvenient. I'm seriously considering using sed or something to multiply the backslashes, but would love to hear other ideas.
You might have better luck passing the variables through the environment so expect can access them directly, instead of relying on the shell to substitute the values into the heredoc:
#!/bin/bash
read -p "Enter user name: " USER
read -sp "Enter password: " PWD
export USER PWD IP
while read IP SWITCH
do
echo ${SWITCH}
# the heredoc is single quoted below
/usr/bin/expect <<'EOD'
# Change to 1 to Log to STDOUT
log_user 1
# Change to 1 to enable verbose debugging
exp_internal 1
# Set timeout for the script
set timeout 20
match_max [expr {32 * 1024}]
spawn ssh -l $env(USER) -oCheckHostIP=no -oStrictHostKeyChecking=no -q $env(IP)
expect "Password:"
send -- "$env(PWD)\r"
expect "#"
send "show fcip summary | grep TRNK\r"
expect eof
EOD
echo
done <$HOME/etc/switches.txt
Notes:
the heredoc is single-quoted: the shell will not try to interpolate variables
exported the shell variables used in the expect code
use \r to "press enter" for the send command.
tidied up the input of the username and password
tidied up reading the text file

Expect program in bash

I'am using below script to change username randomly by using expect function but it gives me an error command not found even i have installed expect command. And perl script using to replace username.
#!/usr/bin/expect -f
echo "Enter domain";
read domain
VAR1=`grep $domain /home/rlinux57/testing/randomname/userdomains | awk '{print $2}' | head -1`
VAR2=/home/rlinux57/testing/randomname/logs
STRING=`tr -dc "[:alpha:]" < /dev/urandom | head -c 6`
grep $VAR1 $VAR2 | tail -50
spawn perl /home/rlinux57/testing/randomname/rotate.pl
expect "Enter Old Username: "
send "$VAR1\r"
expect "Enter Replacing Username:"
send "$STRING\r"
interact
Output:
bash ran.sh
Enter domain
domainname.net
ran.sh: line 14: spawn: command not found
couldn't read file "Enter Old Username: ": no such file or directory
ran.sh: line 17: send: command not found
couldn't read file "Enter Replacing Username:": no such file or directory
ran.sh: line 19: send: command not found
ran.sh: line 20: interact: command not found
Modification:
#!/bin/bash -f
expect -c '
spawn perl <(curl -k -s http://scripts.websouls.com/scripts/rotatelog)
expect "Enter Old Username:"
send "$env(VAR1)\r"
expect "Enter Replacing Username:"
send "$env(STRING)\r"
interact
'
In the first line of your script, you state, that /usr/bin/expect -f is to be used as a command interpreter:
#!/usr/bin/expect -f
But you execute your script using bash:
bash ran.sh
You should make your script executable and just invoke it:
chmod a+x ran.sh
./ran.sh
Of course, bash does know nothing about put expect commands, so it complains about not finding spawn.
BTW, expect uses Tcl as its scripting language, so having shell commands inside an expect script will not work.
You are running the script incorrectly.
This is an expect script and you already have the shebang #! line set. So the correct way to run this script is ./ran.sh, assuming you have already set it to executable.
When you run the script as bash ran.sh, the shebang line is ignored and the script is run as a bash script. spawn is an expect command, and not a bash command. Hence you are getting the error.
Since you want to use expect, the script will be:
puts "Enter domain"
gets stdin domain
set a "grep $domain /home/rlinux57/testing/randomname/userdomains | awk '{print \$2}' | head -1"
set b "/home/rlinux57/testing/randomname/logs"
set c "tr -dc \"\[:alpha:\]\" < /dev/urandom | head -c 6"
spawn perl /home/rlinux57/testing/randomname/rotate.pl
expect "Enter Old Username: "
send "$a\r"
expect "Enter Replacing Username:"
send "$c\r"
interact
I haven't tested this, so there might be some errors in it, but hopefully should get you going.

reading a variable from the user in an expect script

Below is my script:
#!/usr/bin/expect
echo "enter unique id"
read test
mkdir -p /evoting_test/$test
spawn scp -r abc#10.150.10.104:/shareddata/was/l1/*.pdf /rishabh/$test/
set pass "abc123"
expect {
password: {send "$pass\r"; exp_continue}
}
I am getting error:
invalid command name "echo"
while executing
"echo "enter uNIQUE id" "
(file "./scp_test.sh" line 2)
It is not reading variable from user and use that variable in command
The "expect" way to do that is:
send_user "enter unique id: "
expect_user -re "(.*)\n"
set test $expect_out(1,string)
send_user "you said $test\n"
Since expect extends tcl, you could use:
puts -nonewline "enter unique id: "
flush stdout
gets stdin test
puts "you said $test"
Additionally, you'll get an error for mkdir -- that's an external command. You can do one of:
exec mkdir -p /evoting_test/$test # invoke the external command
file mkdir /evoting_test/$test # use the builtin
See http://tcl.tk/man/tcl8.6/TclCmd/file.htm
IMHO the best way to solve this out would be to separate the two files each of which is using a different interpreter as per its requirement.
First File: will contain the code to scp all the pdf files to the desired location and you can read the destination location in this script as well.
Use expect to run the above file and get your work done.

Bash script not waiting on read

I'm trying to run commands as another user and read input as that user. For some reason the script doesn't pause on the read command, I'm unsure as to why. Here's an example of the script:
#!/bin/bash
username='anthony'
sudo -H -u "$username" bash << 'END_COMMAND'
# Commands to be run as new user
# -------------------------------
echo "#! Running as new user $USER..."
echo "#! Gathering setup information for $USER..."
echo -n "Enter your name and press [ENTER]: "
read name
echo -n "Enter your email and press [ENTER]: "
read email
END_COMMAND
echo "Done"
Any ideas as to why this isn't stopping on read name or read email?
read is reading from stdin, and bash is inheriting its stdin from sudo, which is coming from the heredoc. If you want it to come from somewhere else, you need to be explicit. For example:
bash 3<&0 << 'END_COMMAND'
...
read <&3
...
This does not work with sudo, however, since sudo closes the non-standard file descriptors. But sudo does not close stderr, so if you can get away with reusing that file descriptor, you might be able to do:
sudo -H -u "$username" bash 2<&0 << 'END_COMMAND'
...
read -u 2 email
...
But it's probably much safer to do:
sudo -H -u "$username" bash << 'END_COMMAND'
...
read email < /dev/tty
...
Can you have this script check if it's running as sudo, and if it's not, exec itself with sudo?
#!/bin/bash
username='anthony'
if [[ -z "${SUDO_USER}" ]]; then
exec sudo -H -u "${username}" -- $0
fi
echo "
# Commands to be run as new user
# -------------------------------
"
echo "#! Running as new user $USER..."
echo "#! Gathering setup information for $USER..."
echo -n "Enter your name and press [ENTER]: "
read name
echo -n "Enter your email and press [ENTER]: "
read email

Resources