In the first if we want the hostname to appear, which is the 5th field from a file. Then if the IP we give to the host command does not exist, then the command returns message 3 (NXDOMAIN). The script should recognize if the command was "not found". In this case it will
must simply print (-).
#!/bin/bash
ip="$1"
if [ "$ip" ] ; then
host "$ip" | cut -d' ' -f5
elif
[[ "$ip" =~ "[3(NXDOMAIN)]$" ]] ; then
echo "-"
fi
Do u have any solution on this exercise?
You're not testing the result of the host command, you're testing the value of the original $ip variable.
Save the output to a variable, test that variable, then either print the output or - depending on the test.
You don't need to do a regexp match, just match the exact string.
#!/bin/bash
ip="$1"
if [ "$ip" ] ; then
result=$(host "$ip" | cut -d" " -f5)
if [[ $result = "3(NXDOMAIN)" ]] ; then
echo "-"
else
echo "$result"
fi
fi
The answer is much simpler than you think, you don't need to do any matching. You can just use the return code from host
#!/bin/bash
ip="$1"
if domain=$(host "$1"); then
echo "${domain##* }"
else
echo "-"
fi
Proof of Concept
$ testHost(){ if domain=$(host "$1"); then echo "${domain##* }"; else echo "-"; fi }
$ testHost 172.217.6.46
sfo03s08-in-f14.1e100.net.
$ testHost 172.217.6.466
-
#!/bin/bash
if [ -n "$1" ] && [[ $1 =~ ^[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+$ ]] ;then
res=$(host "$1" | cut -d' ' -f5)
if [ "$res" != "3(NXDOMAIN)" ]; then
echo "$res"
else
echo "-"
fi
else
echo "please enter a valid ip"
fi
if you want to cover also ipv6 then I think this will cover it
#!/bin/bash
# ipv4
if [[ $1 =~ ^([[:digit:]]{1,2}|1[[:digit:]][[:digit:]]|2[0-4][[:digit:]]|25[0-5])\.([[:digit:]]{1,2}|1[[:digit:]][[:digit:]]|2[0-4][[:digit:]]|25[0-5])\.([[:digit:]]{1,2}|1[[:digit:]][[:digit:]]|2[0-4][[:digit:]]|25[0-5])\.([[:digit:]]{1,2}|1[[:digit:]][[:digit:]]|2[0-4][[:digit:]]|25[0-5])$ ]]; then
res=`host "$1" | cut -d' ' -f5`
if [ "$res" != "3(NXDOMAIN)" ]; then
echo "$res"
else
# valid ipv4 IP but not connected
echo "-"
fi
# ipv6
elif [[ $1 =~ ^(([[:xdigit:]]{1,4}:){7,7}[[:xdigit:]]{1,4}|([[:xdigit:]]{1,4}:){1,7}:|([[:xdigit:]]{1,4}:){1,6}:[[:xdigit:]]{1,4}|([[:xdigit:]]{1,4}:){1,5}(:[[:xdigit:]]{1,4}){1,2}|([[:xdigit:]]{1,4}:){1,4}(:[[:xdigit:]]{1,4}){1,3}|([[:xdigit:]]{1,4}:){1,3}(:[[:xdigit:]]{1,4}){1,4}|([[:xdigit:]]{1,4}:){1,2}(:[[:xdigit:]]{1,4}){1,5}|[[:xdigit:]]{1,4}:((:[[:xdigit:]]{1,4}){1,6})|:((:[[:xdigit:]]{1,4}){1,7}|:)|fe80:(:[[:xdigit:]]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])|([[:xdigit:]]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[[:digit:]]){0,1}[[:digit:]]))$ ]]; then
res=`host "$1" | cut -d' ' -f5`
if [ "$res" != "3(NXDOMAIN)" ]; then
echo "1. $res"
else
# valid ipv6 IP but not connected
echo "2. -"
fi
else
echo "Please enter a valid IP"
fi
Note: For some versions of bash the -4 and -6 options do not work.
Thanks to Léa Gris for pointing out the locales problem.
Inspired from https://helloacm.com/how-to-valid-ipv6-addresses-using-bash-and-regex/
I have a simple script that nmaps from a list of ip's, and returns any ips that have port 80 open. The problem is when 80 is closed, instead of no return, Im getting "=: command not found" as it is attempting to compare a blank/empty variable.
#!/bin/bash
for i in$(cat filename.txt); do
str=$(nmap $i |grep 80 | cut -d ' ' -f2)
if($str = "open"); then
echo port 80 on $i is open
fi
done
When port 80 is closed, $str is getting nothing for a value, then when I try to compare nothing to the string "open", im getting "=: command not found". How do I check if $str has a value before comparing it to a string? I tried
if (! -z $str); then
which I thought meant
if $str is not null, then,
but could not get it to work properly. I certainly believe I understand why its is behaving as it is, I just dont know how to correct it.
With GNU bash:
#!/bin/bash
port="80"
while read -r host; do
str=$(nmap "$host" -p "$port" | grep "^$port")
ret="${PIPESTATUS[0]}" # returncode of nmap
if [[ $ret != 0 ]]; then
echo "error"
exit 1
fi
# check if $str contains "open"
if [[ $str =~ open ]]; then
echo "port $port on $host is open"
else
echo "port $port on $host is not open"
fi
done <filename.txt
I assume filename.txt contains only one IP or hostname per line.
Output (example):
port 80 on 10.20.30.40 is not open
port 80 on localhost is open
Here's a version using netcat's exit status:
#!/bin/bash
while read host; do
nc -zw2 $host 80 &>/dev/null && state=open || state=closed
echo "port 80 on $host is $state"
done < filename.txt
Thank you all for the help, Cyrus I like yours a lot, better than what I came up with, and Cole I was very happy to see it done with netcat. Here is what I eventually arrived at
#!/bin/bash
for i in$(cat targetlist.txt); do --multiple people say this doesnt work
str=$(nmap -p 80 $i | grep 80 | cut -d ' ' -f2) --im using bash 4.2.37(1)
if [[ ! -z $str && $str = "open" ]] ; then
echo port 80 on $i is open
fi
done
I want to make a chat script in bash and I've started out pretty basic and you start off by login in with any name you want, no password required and then you can write commands like connect, clear, exit and so on.
But I want to be able to actually start a chat between two people in the terminal window. Now, I've read a little about IRC but I don't know how to get it to work.
Any help would be appreciated
Here's my script:
#!/bin/bash
ver=1.0
my_ip="127.0.0.1"
function connect()
{
echo -n "Ip-address: "
read ip
if [ -n "$ip" ]
then
exit
fi
}
function check()
{
if [ "${c}" = "connect" ] || [ "${c}" = "open" ]
then
connect
fi
if [ "${c}" = "clear" ] || [ "${c}" = "cls" ]
then
clear
new
fi
if [ "${c}" = "quit" ] || [ "${c}" = "exit" ]
then
echo "[Shutdown]"
exit
fi
}
function new()
{
echo -n "$: "
read c
if [ -n "${c}" ]
then
check
else
echo "Invalid command!"
new
fi
}
function onLogin()
{
clear
echo "Logged in as ${l_name} on [${my_ip}]"
new
}
function login()
{
echo -n "Login: "
read l_name
if [ -n "${l_name}" ]
then
onLogin
else
echo "Invalid input!"
login
fi
}
#execution
clear
echo "Bash Chat v${ver} | Mac"
login
If you truly want to write a chat client in pure bash, it would have to be local chat (same physical machine) rather than network chat.
Assuming that this is adequate for your needs, you can use named pipes (FIFO)
Illustration
Here is an example that illustrates what you can do with two pipes (for bidirectional communication):
mkfifo /tmp/chatpipe1 ; mkfifo /tmp/chatpipe2
(In terminal one): cat > /tmp/chatpipe1
(In terminal two): cat /tmp/chatpipe2
( same and in reverse for Terminals 3 and 4 )
This illustrates that you can have 4 processes in bash, two writing to two pipes and two reading from the same two pipes. Two terminals on the left are for Bob, two on the right are for John.
You can organize all of this into a single script if you understand bash backgrounding, loops (and hopefully traps to clean up on shutdown).
Script
Here is a rudimentary version:
#!/bin/bash
if [ -z "$2" ] ; then
echo "Need names of chat pipes (yours and other's), eg $0 bob john"
exit 1
fi
P1=/tmp/chatpipe${1}
P2=/tmp/chatpipe${2}
[ -p "$P1" ] || mkfifo $P1
[ -p "$P2" ] || mkfifo $P2
# Background cat of incoming pipe,
# also prepend current date to each line)
(cat $P2 | sed "s/^/$(date +%H:%M:%S)> /" ) &
# Feed one notice and then STDIN to outgoing pipe
(echo "$1 joined" ; cat) >> $P1
# Kill all background jobs (the incoming cat) on exit
trap 'kill -9 $(jobs -p)' EXIT
# (Probably should delete the fifo files too)
And a chat session:
Note that this script is only a simple example. If bob and john are different unix accounts, you'll have to be more careful with file permissions (or if you don't care about security, mkfifo -m 777 ... is an option)
A chatroom can be made in literally 10 lines of bash. I posted one on my github earlier today
https://github.com/ErezBinyamin/webCatChat/blob/master/minimalWbserver
Can handle “n” users. They just need to connect to :1234
Here's the code:
#!/bin/bash
mkdir -p /tmp/webCat && printf "HTTP/1.1 200 OK\n\n<!doctype html><h2>Erez's netcat chat server!!</h2><form>Username:<br><input type=\"text\" name=\"username\"><br>Message:<br><input type=\"text\" name=\"message\"><div><button>Send data</button></div><button http-equiv=\"refresh\" content=\"0; url=129.21.194:1234\">Refresh</button></form>" > /tmp/webCat/webpage
while [ 1 ]
do
[[ $(head -1 /tmp/webCat/r) =~ "GET /?username" ]] && USER=$(head -1 /tmp/webCat/r | sed 's#.*username=##' | sed 's#&message.*##') && MSG=$(head -1 /tmp/webCat/r | sed 's#.*message=##' | sed 's#HTTP.*##')
[ ${#USER} -gt 1 ] && [ ${#MSG} -gt 1 ] && [ ${#USER} -lt 30 ] && [ ${#MSG} -lt 280 ] && printf "\n%s\t%s\n" "$USER" "$MSG" && printf "<h1>%s\t%s" "$USER" "$MSG" >> /tmp/webCat/webpage
cat /tmp/webCat/webpage | timeout 1 nc -l 1234 > /tmp/webCat/r
unset USER && unset MSG
done
#!/bin/bash
# portcheck tool
usage()
{
echo -e "\n USAGE: ./${0##*/} [host|ip] \n"
exit
}
check_port()
{
local host=${1}
local port=${2}
if [ nc -w 5 -z host port ] && [ nc -w 5 -z host port ]
then
echo -e "\a\n => Port ${port} at ${host} is open"
else
echo -e "\a\n => Port ${port} at ${host} is closed"
fi
}
[[ $# -ne 2 ]] && usage
check_port ${1} ${2}
When I run the following command:
bash portOpenBash.sh 127.0.0.1 434
I get the following error:
portOpenBash.sh: line 14: [: too many arguments
I try to put quotes between the macro expression, but I get the same error.
Problem seems to be in your if conditions here:
if [ nc -w 5 -z host port ] && [ nc -w 5 -z host port ]
You probably want to check for non empty output of both commands like this:
if [ -n "$(nc -w 5 -z $host $port)" ] && [ -n "$(nc -w 5 -z $host $port)" ]
OR in BASH:
if [[ -n "$(nc -w 5 -z $host $port)" && -n "$(nc -w 5 -z $host $port)" ]]
EDIT:
OR else if you just want to check return codes then remove surrounding [ and ]:
if nc -w 5 -z $host $port && nc -w 5 -z $host $port
SO I wrote a script that can change the SSH port on CentOS but for some reason I'm encountering this error:
sshchangecOS6.sh: line 36: syntax error: unexpected end of file
This is the script:
#! /bin/bash
# This script changes the ssh port for logins on CentOS 5 and 6
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root"
exit 2
read -r -p "Would you like to change the ssh port? [Y/N] " response
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]
then
read -p "What would you like to change the port to? (Chose between 1024-65535) " sshportconfig
if (( ("$sshportconfig" > 1024) && ("$sshportconfig" < 65535) )); then
echo "Port $sshportconfig" >> /etc/ssh/sshd_config
echo "--------------------------------------------------------------------"
echo ""
echo ""
echo "SSH port has been changed to: $sshportconfig. Written by Sincere the Minotaur."
echo ""
echo ""
echo "--------------------------------------------------------------------"
else
echo "Port chosen is incorrect."
exit 1
fi
else
sshPort=$(grep "Port" /etc/ssh/sshd_config) | head -n 1
echo "--------------------------------------------------------------------"
echo ""
echo ""
echo "SSH is still: $sshPort"
echo "Written by Sincere the Minotaur."
echo ""
echo "---------------------------------------------------------------------"
exit 1
fi
exit 0
Could someone explain where the errors are?
There is no fi for the first if if [[ $EUID -ne 0 ]]; then. You need to close every if with a fi.