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.
Related
I am currently writing the following script that logs into a remote server and runs couple of commands to verify the performance of the server and prints a message based on the output of those commands .But the ssh doesn't work and returns the stats of the server that hosts the script instead .
Script
#!/bin/bash
#######################
#Function to add hosts to the array
#the following function takes the ip addresses provided while the script is run and stores them in an array
#######################
Host_storing_func () {
HOST_array=()
for i in $# ;do
HOST_array+=(${i});
done
#echo ${HOST_array[*]}
}
#######################
#Calling above function
#######################
Host_storing_func "$#"
############################################################
#Collect Stats of Ping,memory,iowait time test function
############################################################
b=`expr ${#HOST_array[*]} - 1 `
for i in `seq 0 $b` ;do
sshpass -f /root/scripts/passwordFile.txt /usr/bin/ssh student35#${HOST_array[${i}]} << HERE
echo `hostname`
iowaittm=`sar 2 2|awk '/^Average/{print $5};'`
if [ $iowaittm > 10 ];then
echo "IO ==> BAD"
else
echo "IO ==> GOOD"
fi
memoryy=`free -m |grep Swap|awk '{if($2 == 0) print 0;else print (($4 / $2 ) * 100)}'`
if [ ${memoryy} < '10' ] ;then
echo "memory ==> good"
elif [[ "${memory}" -ge 0 ]] && [[ "${memory}" -le 10 ]];then
echo "No Swap"
else
echo "memory ==> bad"`enter code here`
fi
ping -w2 -c2 `hostname` | grep "packet loss"|awk -F, '{print $3}'|awk -F% '{print $1}'|sed 's/^ *//'|awk '{if ($1 == 0) print "Yes" ;else print "No"}'
HERE
done
Output : oc5610517603.XXX.com is the name of the source server
[root#oc5610517603 scripts]# ./big_exercise.sh 9.XXX.XXX.XXX 9.XXX.XXX.XXX
Pseudo-terminal will not be allocated because stdin is not a terminal.
oc5610517603.XXX.com
IO ==> GOOD
No Swap
ping: oc5610517603.ibm.com: Name or service not known
Pseudo-terminal will not be allocated because stdin is not a terminal.
oc5610517603.XXX.com
IO ==> GOOD
No Swap
ping: oc5610517603.XXX.com: Name or service not known
thanks for checking the script , I figured out a way to solve the problem
It is the sshpass command that is causing issue , you just have to put the opening HERE in single quotes if you want to use variables with in the HEREdoc but if the variables are calculated before ssh then you don't have to put opening HERE in single quotes
sshpass -f /root/scripts/passwordFile.txt /usr/bin/ssh -T student35#${i} << 'HERE'
after I changed the sshpass command as above my script worked
I have modified your script a bit.
As suggested by #chepner, I am not using the Host_storing_func.
Heredocs for sshpaas are somewhat tricky. You have to escape every back-tick and $ sign in the heredoc.
Notice the - before the heredoc start, it allows you to indent the heredoc body. Also, try to avoid back-ticks when you can. use $(command) instead.
Hope it helps.
#!/bin/bash
#######################
#Function to add hosts to the array
#the following function takes the ip addresses provided while the script is run and stores them in an array
#######################
array=( "$#" )
user="student35"
############################################################
#Collect Stats of Ping,memory,iowait time test function
############################################################
for host in ${array[#]}; do
sshpass -f /root/scripts/passwordFile.txt /usr/bin/ssh -l ${user} ${host} <<-HERE
thishost=\$(hostname)
echo "Current Host -> \$thishost";
iowaittm=\`sar 2 2|awk '/^Average/{print \$5}'\`
if [ \$iowaittm > 10 ]; then
echo "IO ==> BAD"
else
echo "IO ==> GOOD"
fi
memory=\$(free -m | grep Swap | awk '{if(\$2 == 0) print 0;else print ((\$4 / \$2 ) * 100)}')
if [ \${memory} < '10' ] ;then
echo "memory ==> good"
elif [[ "\${memory}" -ge 0 ]] && [[ "\${memory}" -le 10 ]]; then
echo "No Swap"
else
echo "memory ==> bad"\`enter code here\`
fi
ping -w2 -c2 \`hostname\` | grep "packet loss"|awk -F, '{print \$3}'|awk -F% '{print \$1}'|sed 's/^ *//'|awk '{if (\$1 == 0) print "Yes" ;else print "No"}'
HERE
done
I have the following code in bash:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
while true; do
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ;
then
echo -e "\a\n => Port at host is open"
break
else
echo -e "\a\n => Port at host is closed"
break
fi
}
For some reason, I get the following error:
syntax error near unexpected token `}'
`}'
I don't understand why: } is closing the scope of the function.
You need a done line to terminate your while loop, between the fi line and the closing brace }.
However, I'm not entirely certain why you even have the while true loop since you break out of it regardless of whether the if evaluates to true or false. Hence it's superfluous, unless you plan on changing the behaviour of one of those blocks at some point.
If you're not planning that, you're better off with the much simpler:
check_port()
{
local host=${1}
local port=${2}
echo $host
echo $port
if nc -w 5 -z 127.0.0.1 111 && nc -w 5 -z 127.0.0.1 5001 ; then
echo -e "\a\n => Port at host is open"
else
echo -e "\a\n => Port at host is closed"
fi
}
I'm also not entirely certain of the sanity of passing in the host and port and then ignoring them (instead using localhost with two hard-coded ports).
However, I'm going to assume that you're still in the development/testing phase rather than the possibility you've gone insane :-)
The done at the end of the while loop is missing
....
break
fi
done;
}
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
I am trying store the output of command to a variable in a script and print the result depending on output stored in variable..
For example, in this script, I am trying print the status of an agent installed on few systems read from lab.txt file. If the status matches with "isrunning", it prints that "agent is installed".
~]# cat lab.txt
192.168.1.1
192.168.1.2
Here is the script -
#!/bin/bash
while read host; do
status=$(ssh -n root#$host /opt/agent/bin/agent.sh status | awk 'NR==1{print $3 $4}')
if [ $status != isrunning ]
then
echo "agent is not installed"
else
echo "agent is installed"
fi
done < lab.txt
The issue here is, if the command returns an error as becuase the /opt/agent directory was not present on system 192.168.1.2, the "agent is not installed" message is not printed. What could be wrong here?
~]# ./script.sh
root#192.168.1.1:
agent is installed
root#192.168.1.2:
bash: /opt/agent/bin/agent.sh: No such file or directory
./script.sh: line 5: [: !=: unary operator expected
agent is installed
$status is not initialized, so the condition [ status != isrunning ] is not satisfied. Something like:
if [ "$status" != isrunning ]
should solve this and get rid of your error of unary operator expected too.
I am working on a script to read from a file having multiple IP addresses, login to each system (no ssh keys involved and manually entering password), execute a command depending on OS type and print the result.
Here is how IPs are defined in the hosts.txt file
#~] cat hosts.txt
10.6.3.131
10.6.3.132
10.6.3.11
10.6.3.12
When I execute the below script, the following errors are shown. Also, The script does not prompt for 2nd and rest IPs in the list. What could be causing this?
# ./hq-test1.sh
root#10.6.3.131's password:
awk: cmd. line:1: NR==1{print
awk: cmd. line:1: ^ unexpected newline or end of string
bash: line 2: [: !=: unary operator expected
10.6.3.131 == PASS
This is the script used in test :
#!/bin/bash
while read HOST; do
if ssh root#$HOST '
STATUS=`awk 'NR==1{print $1}' /etc/*release`
[ $STATUS != "CentOS" ]
'; then
echo "$HOST == FAIL"
else
echo "$HOST == PASS"
fi
done < hosts.txt
Your script isn't closing stdin while running the ssh command so only the first host of the list is processed.
I also simplified the test, as awk is able to check the OS name and the temporary variable is unnecessary.
while read host; do
if ssh -n root#$host '[ "$(awk "/CentOS/{print}" /etc/*release)" ] '
then
echo "$host == PASS"
else
echo "$host == FAIL"
fi
done < hosts.txt
This worked for me. As I already wrote, it's just a quoting issue.
#!/bin/bash
echo localhost | while read HOST; do
if ssh root#$HOST '
STATUS=`awk "NR==1{print \$1}" /etc/*release`
[ $STATUS != "CentOS" ]
'; then
echo "$HOST == FAIL"
else
echo "$HOST == PASS"
fi
done