How to send test to a certain line using Bash Scripting - bash

I know there are other posts on this but i cannot get any of them to work. My problem is that i want to create a script on my rpi to automatically change wifi networks and change eth0 between static and dhcp. It is not yet finished i am currently only working on the wireless part. But the script so far reads...
#!/bin/bash
ANS=''
ssid=''
psk=''
file='/etc/network/interfaces'
function wireless {
echo 'The wireless network '$ssid' has now been set up'
start
}
function ssid {
echo 'What is your Network SSID?'
echo -e '> \c'
read ssid
echo 'You entered '$ssid'. Is this correct? (y/n)'
echo -e '> \c'
read ANS
if [ $ANS = 'y' ]; then
psk
else
echo 'Please renter your SSID'
ssid
fi
}
function psk {
echo 'What is your Network PSK?'
echo -e '> \c'
read psk
echo 'You entered '$psk'. Is this correct? (y/n)'
echo -e '> \c'
read ANS
if [ $ANS = 'y' ]; then
wireless
else
echo 'Please renter your PSK'
psk
fi
}
function start {
echo 'What do you want to do?'
echo ''
echo 'Press w to set up wireless ssid and psk'
echo 'Press s to change eth0 to a static ip address'
echo 'Press d to change eth0 to a dhcp ip address'
echo ''
echo 'Or press ctrl+c to quit'
echo -e '> \c'
read ANS
if [ $ANS = 'w' ]; then
ssid
else
if [ $ANS = 's' ]; then
static
else
if [ $ANS = 'd' ]; then
dhcp
fi
fi
fi
}
#backup of /etc/network/interfaces
#auto lo
#iface lo inet loopback
#iface eth0 inet dhcp
#iface eth0 inet static
# address ###########
# netmask #############
# broadcast ###########
# gateway ##########
#
#allow-hotplug wlan0
#
#auto wlan0
#
#iface wlan0 inet dhcp
#wpa-ssid "Home Network"
#wpa-psk "psk"
start
exit 0
So thats all fine but in the function wireless i want to send the psk and the ssid to lines 15 and 16 of /etc/network/interfaces. Please could someone tell me the best method to do this by.
Thanks

You can perform automatic edits using sed like this:
sed -i "s/^wpa-ssid.*\$/wpa-ssid \"$ssid\"/" /etc/network/interfaces
This command matches any complete line beginning with wpa-ssid and replaces it with "wpa-ssid" followed by the contents of the $ssid variable. ^wpa-ssid.*\$ is the match pattern. ^ means the beginning of the line, .* means match anything, and \$ means the end of the line. wpa-ssid \"$ssid\"/ is what to replace it with.
The -i option means to edit the file, rather than print the result to standard out.
psk will work the same way.
You should consider having your script back up the file the first time it is run.

If I understand, you want to replace the quoted text in line 15 of /etc/network/interfaces with SSID text, and that of line 16 with PSK text. For example,
#wpa-ssid "Home Network"
#wpa-psk "psk"
might change to
#wpa-ssid "new-Network"
#wpa-psk "new-psk"
I don't see in your script code what variables you might have the new SSID and PSK names in, but if they were in variables called SSID and PSK, and FILE="/etc/network/interfaces", you could say:
sed -i "s/^#wpa-ssid.*/#wpa-ssid \"$SSID\"/; \
s/^#wpa-psk.*/#wpa-psk \"$PSK\"/" $FILE
The outer quotes are double-quotes to allow bash variable expansion. The inner double-quotes are back-slash quoted. Remove the back-slash at the end of the first line if you put the sed command on a single line. Also, when trying this out, make a copy of your interfaces file and set FILE to the name of the copy; run the sed command, then diff the copy with the original to check correct operation.

Related

How to respond to a prompt within a shell script

I'm trying to answer a command prompt for the user within the script.
Command
ufw enable
Prompt
Command may disrupt existing ssh connections. Proceed with operation (y|n)?
Piece of code that I'm using but its not working properly:
function awk_ufw {
ufw status | grep Status | awk '{print $2}'
}
.
.
.
local CHECK_STATUS=$(awk_ufw)
if [ $CHECK_STATUS == "active" ]
then
echo "----------------------------"
echo "Firewall is already enabled!"
echo "----------------------------"
else
read -p "Before you enable the firewall, please ensure that at least inbound port for your ssh connection is open, otherwise you'll be locked out if ssh is the only way to access the system! [Please type \"understood\" to continue]: " UNDERSTOOD_PROMPT
if [[ $UNDERSTOOD_PROMPT == "understood" || $UNDERSTOOD_PROMPT == "UNDERSTOOD" ]]
then
ufw enable <EOF
y
EOF
if [ $? == "0" ]
then
echo "-----------------"
echo "Firewall enabled!"
echo "-----------------"
else
echo "------------------------------------------------------------------------------------------------------"
echo "Something went wrong during the process, unsure whether firewall was enabled, please recheck manually!"
echo "------------------------------------------------------------------------------------------------------"
fi
else
echo "------------------------------------------------------"
echo "Skipping the step since \"Understood\" wasn't entered!"
echo "------------------------------------------------------"
fi
fi
Code break on
ufw enable <EOF
y
EOF
Before you enable the firewall, please ensure that at least inbound port for your ssh connection is open, otherwise you'll be locked out if ssh is the only way to access the system! [Please type "understood" to continue]: understood
./script.sh: line 84: EOF: No such file or directory
./script.sh: line 85: y: command not found
./script.sh: line 86: EOF: command not found
------------------------------------------------------------------------------------------------------
Something went wrong during the process, unsure whether firewall was enabled, please recheck manually!
------------------------------------------------------------------------------------------------------
Any suggestions how to correct it/improve it?
Thank you in advance!
The end marker in heredocs cannot be indented:
cat << MARKER
content
MARKER
works, while:
cat << MARKER
content
MARKER
doesn't.
And heredocs uses two lt symbols: << MARKER. < thing is a redirection.
In your case it would be:
if [[ $UNDERSTOOD_PROMPT == "understood" || $UNDERSTOOD_PROMPT == "UNDERSTOOD" ]]
then
ufw enable <<EOF
y
EOF
But you might consider piping echo y | instead:
echo y | ufw enable
Which is effectually the same in your case.
FYI awk can do pattern matching, to there is no need to you to pipe grep | awk:
awk_ufw() {
ufw status | awk '/Status/ {print $2}'
}
Or possible just check the first field:
awk_ufw() {
ufw status | awk '$1 == "Status" {print $2}'
}
A quick scan of the man page shows you can avoid the problem all together:
By default, ufw will prompt when enabling the firewall while running
under ssh. This can be disabled by using 'ufw --force enable'.
So using:
ufw --force enable
in your script avoids the issue of having to pass a keypress in.

Issue with ping sweep that reads in an IP address

The main issue I am having with this is pinging the read in IP address. It always says that the address is down.
Ping_Sweep()
{
echo -e '\n'
echo '----- Ping Sweep -----'
echo -e '\n'
command date >> pingresults.tx
echo "Enter in the first three number sequences of an IP address (ex. ###.###.###): "
read -r ip_address
for x in $ip_address
do
echo "IP address being pinged: $ip_address"
if ping –c 1 "$x" &> /dev/null
then
echo "IP: $x is up."
else
echo "Ping failed. $x is down."
fi
done
Main_Menu
}
ping –c should be ping -c. Your original command has an en dash. This is usually caused by copying code rendered by a bad blog framework.

Is there a way to display function output in bash command

Have a simple bash script I am working on with Mac, but I am having one issue.
#!/bin/bash
# Pull users IP from getifaddr on specfic port
myip ( ) {
#ipconfig getifaddr ppp0
local _ip _myip _line _nl=$'\n'
while IFS=$': \t' read -a _line ;do
[ -z "${_line%inet}" ] &&
_ip=${_line[${#_line[1]}>4?1:2]} &&
[ "${_ip#127.0.0.1}" ] && _myip=$_ip
done< <(LANG=C /sbin/ifconfig)
printf ${1+-v} $1 "%s${_nl:0:$[${#1}>0?0:1]}" $_myip
}
printf "My ip: %"
myip
# Static server IP stored
serverip ( ) {
echo 192.168.12.110
}
serverip
## Command to add them together
sudo route add $myip $severip
So far the functions work, but the sudo route command does not since I am guessing there is no return value.
What I need it to do it output the myip IP address and the serverip IP address onto the line so the command can run in a single command.
For example: sudo route add 192.168.0.1 192.168.0.2
Right now, it tells me "myip is not a valid routing address" as I believe it is taking the literal 4 character string "myip" and not the IP address.
Bash's command substitution might help:
sudo route add $(myip) $(serverip)

shell script to find dynamic public ip address in ubuntu does not show any output

I wrote the following script to find my dynamic public IP address and save how often it is changes
#!/usr/bin/env bash
ip=0
change=0
for ((count = 10000; count != 0, change == 10; count--)); do
fetch="$(dig +short myip.opendns.com #resolver1.opendns.com)"
dig +short myip.opendns.com #resolver1.opendns.com >>/home/nik/Desktop/file.txt
if [ $ip == 0 ]; then
ip=fetch
elif [ $ip != "$fetch" ]; then
change++
echo $ip
echo " changed to "
echo "$fetch"
echo " at "
echo date
else
echo ""
fi
echo "123"
sleep 13
(( count--))
done
I saved file as script.sh and changed it's executable permissions using
chmod +x script.sh
When I independently run dig command(in next line) or echo command directly in terminal, they log output to file without any problem
dig +short myip.opendns.com #resolver1.opendns.com>>/home/nik/Desktop/file.txt
but when I run the script, It shows no output nor does it log anything into text file.
I use Ubuntu 19.10 if it matters.
Edit: added shebang and changed wait to sleep
You have change=0 in the beginning of your file, and then depend on change == 10 in the conditional expression of your for loop.
I think you should review your code first :-)
A good place to start with a script that tracks public IP Address changes might be this guy:
#!/usr/bin/env bash
CURRENT_IP="$(timeout 5 dig +short myip.opendns.com #resolver1.opendns.com 2>/dev/null)"
num_changes=0
while [ 1 ]
do
NEW_IP="$(timeout 5 dig +short myip.opendns.com #resolver1.opendns.com 2>/dev/null)"
if echo "${CURRENT_IP}" | grep -q "${NEW_IP}"
then
echo "IP is the same" > /dev/null
else
let num_changes++
echo "${num_changes}: ${CURRENT_IP} -> ${NEW_IP}"
CURRENT_IP="${NEW_IP}"
fi
done
There are two variables being used, CURRENT_IP and NEW_IP
They are both being updated the same way timeout 5 dig +short ... 2>/dev/null
The timeout serves to ensure our script never hangs forever
The 2>/dev/null serves to filter error messages away
The num_changes variable keeps track of the number of times the IP changed
The only time this script will ever print any message at all is when your address changes
Example output: [NUM_CHANGES]: [LAST ADDRESS] -> [NEW ADDRESS]
1: 75.72.13.89 -> 74.76.77.88
2: 75.72.13.88 -> 74.76.77.87
3: 75.72.13.87 -> 74.76.77.86

BASH: IF statement doesn't work with empty string from WHILE loop

The first if statement doesn't work if there is no output from the command. I also tried to evaluate the exit status but this also doesn't work?
unhide-tcp output:
# unhide-tcp
Unhide-tcp 20130526
Copyright © 2013 Yago Jesus & Patrick Gouin
License GPLv3+ : GNU GPL version 3 or later
http://www.unhide-forensics.info
Used options:
[*]Starting TCP checking
Found Hidden port that not appears in ss: 1025
Found Hidden port that not appears in ss: 1026
[*]Starting UDP checking
Script:
#!/usr/bin/env bash
unhide-tcp | grep "^Found" | while IFS=":" read -a PORT; do
if [ -z ${PORT[1]} ]; then
echo "No hidden ports found."
elif [ -n ${PORT[1]} ]; then
echo ${PORT[#]}
fi
done
I think what you simply need is:
unhide-tcp | grep "^Found" || echo "No hidden ports found."
It would print lines like Found Hidden port that not appears in ss: 1025 and if those lines aren't found, script would print "No hidden ports found." instead - because grep returns nonzero if it doesn't find a match.
If you want to condense your output of ports into a single line, you can use sed and readarray with process substitution:
readarray -t PORTS < <(exec unhide-tcp | sed -nr 's|^Found.*: ([0-9]+).*|\1|p')
[[ ${#PORTS[#]} -gt 0 ]] && echo "${PORTS[#]}" || echo "No hidden ports found."
It could give an output like 1025 1026 or No hidden ports found..
Flags such as -z require an argument. In your example the expansion of the $PORT variable may be blank. Wrap the variable name in double quotes.
if [ -z "${PORT[1]}" ]; then ...
You will be better off using awk like this:
unhide-tcp | awk -F':' '/Found/ && NF==2{c++; print} END{if (c==0) print "No hidden ports found"}'
When I used it on the input shown in your question I get this output:
Found Hidden port that not appears in ss: 1025
Found Hidden port that not appears in ss: 1026

Resources