Here is my code to find the details of the domain. The domain can be feed as following:
bash script.sh domain1.com domain2.com
bash script.sh domains.txt <-- not completed
The output should be in following format:
IP Address: 192.168.101.2
Server Name: servername.com
NS1: ns1.ournameserver.com
NS2: ns2.ournameserver.com
NS3: ns3.ournameserver.com
Datacenter: datacenter-name
Region: datacenter-13
Server Role: cPanel Web Server
Env: Production
Owner: xxxxxxxxxxx
Status: Active
IP Address: 192.168.101.2
Server Name: servername
NS1: ns1.ournameserver.com
NS2: ns2.ournameserver.com
NS3: ns3.ournameserver.com
Datacenter: datacenter-name
Region: datacenter-13
Server Role: cPanel Web Server
Env: Production
Owner: xxxxxxxxxxx
Status: Suspended
If it is in cloudflare:
Domain name: test.com
IP Address: 192.168.101.1
Server ID: N/A
Server Name: N/A
NS1: LYNDA.CLOUDFLARE.COM
NS2: DYN.CLOUDFLARE.COM
Datacenter: OVH
Region: HETZ-C3
Server Role: cPanel Web Server
Env: Production
Owner: xxxxxxxxxxx
Now it is only giving result in normal format, it also needs to be in JSON format
script.sh
#!bin/bash
HIP="$@"
check ()
{
regexp="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
nameserver=('@ns1.ournameserver.com' '@ns2.ournameserver.com' '@ns3.ournameserver.com')
for j in ${nameserver[@]}
do
IPADD=`dig $j $i +noall +answer | grep "A" | awk '{print 5ドル}'`
if [[ $IPADD =~ $regexp ]]
then
echo "IP Address = " $IPADD
ServerName=`nslookup $IPADD | grep -o -P '(?<=\=).*(?=.)'`
echo "ServerName = " $ServerName
DATA=`whois $IPADD | egrep 'org-name|OrgName' | awk '{print 2ドル.3ドル}'`
echo "Data Center = " $DATA
break
fi
done
}
check2 ()
{
Pinging=`ping $i -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '\(|\)' ' '`
IPADD=`awk '{print 2ドル}' <<< $Pinging`
echo "IP Address = " $IPADD
ServerName=`awk '{print 1ドル}' <<< $Pinging`
echo "Server Name = " $ServerName
}
for i in ${HIP[@]}
do
echo "Domain Name = " $i;
nsserver=`nslookup -type=ns $i | grep 'nameserver' | grep -o -P '(?<=ns.).*(?=.)' | head -n 1`
if [[ $nsserver == 'cloudflare.com' ]]
then
check
if ! [[ $IPADD =~ $regexp ]]
then
echo "This Domain does not belong to this server."
fi
else
check2
fi
whois $i | grep "Registrant Name"
nslookup -type=ns $i | grep nameserver | awk '{print 2,ドル3,ドル4ドル}'
var=`curl -sL $i | grep '<title>' | tr -d ' ' | grep -o -P '(?<=Account).*(?=ed)'`
if [[ $var == 'Suspend' ]]
then
echo "Status = Account Suspended"
else
var=`curl -I $i 2>/dev/null | head -n 1 | cut -d$' ' -f2-3`
echo "Status = " $var
fi
printf '%*s' 100 | tr ' ' '#'
echo ''
done
2 Answers 2
Shellcheck reports quite a few issues you might want to correct:
shellcheck -f gcc 197939.sh
197939.sh:2:5: warning: Assigning an array to a string! Assign as array, or use * instead of @ to concatenate. [SC2124]
197939.sh:5:24: note: Backslash is literal in "\.". Prefer explicit escaping: "\\.". [SC1117]
197939.sh:5:36: note: Backslash is literal in "\.". Prefer explicit escaping: "\\.". [SC1117]
197939.sh:5:48: note: Backslash is literal in "\.". Prefer explicit escaping: "\\.". [SC1117]
197939.sh:8:14: error: Double quote array expansions to avoid re-splitting elements. [SC2068]
197939.sh:10:17: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:10:22: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:10:25: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:13:38: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:14:28: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:14:38: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:15:38: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:16:22: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:16:29: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:16:38: note: egrep is non-standard and deprecated. Use grep -E instead. [SC2196]
197939.sh:17:39: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:25:13: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:25:19: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:26:11: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:26:33: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:27:26: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:28:16: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:28:38: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:29:27: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:32:10: error: Double quote array expansions to avoid re-splitting elements. [SC2068]
197939.sh:34:27: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:35:14: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:35:33: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:47:11: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:48:23: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:49:9: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:49:19: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:54:13: note: Use $(..) instead of legacy `..`. [SC2006]
197939.sh:54:22: note: Double quote to prevent globbing and word splitting. [SC2086]
197939.sh:55:26: note: Double quote to prevent globbing and word splitting. [SC2086]
Additionally, I recommend making regexp
, nameserver
, IPADD
, ServerName
and DATA
local within check()
(and giving most of them better names, or inlining the single-use ones), and making Pinging
, IPADD
and ServerName
local within check2()
:
check ()
{
local regexp='^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
local nameserver=('@ns1.ournameserver.com' '@ns2.ournameserver.com' '@ns3.ournameserver.com')
for j in "${nameserver[@]}"
do
local IPADD
IPADD=$(dig "$j" "$i" +noall +answer | grep "A" | awk '{print 5ドル}')
if [[ $IPADD =~ $regexp ]]
then
echo "IP Address = $IPADD"
echo "ServerName = $(nslookup "$IPADD" | grep -o -P '(?<=\=).*(?=.)')"
echo "Data Center = $(whois "$IPADD" | grep -E 'org-name|OrgName' | awk '{print 2ドル.3ドル}')"
break
fi
done
}
check2 ()
{
local Pinging
Pinging=$(ping "$i" -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '\(|\)' ' ')
echo "IP Address = $(awk '{print 2ドル}' <<<"$Pinging")"
echo "Server Name = $(awk '{print 1ドル}' <<<"$Pinging")"
}
Prefer to pass "$i"
as an argument to check()
, rather than communicating via global variables. And communicate the $IPADD
from the last successful nameserver by other means.
Instead of extracting substrings using grep
, then testing them with [[ =~ ]]
, simply use grep -q
for the test.
Improved code
There's still plenty left to work on (for example, repeated whois
invocations).
#!/bin/bash
check ()
{
local regexp='^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
local nameserver=('ns1.ournameserver.com' 'ns2.ournameserver.com' 'ns3.ournameserver.com')
for j in "${nameserver[@]}"
do
local IPADD
IPADD=$(dig "@$j" "1ドル" +noall +answer | grep -w 'A' | awk '4ドル=="A" {print 5ドル}')
if [[ $IPADD =~ $regexp ]]
then
echo "IP Address = $IPADD"
echo "ServerName = $(nslookup "$IPADD" | grep -o -P '(?<=\=).*(?=.)')"
echo "Data Center = $(whois "$IPADD" | grep -E 'org-name|OrgName' | awk '{print 2ドル.3ドル}')"
return 0
fi
done
return 1
}
check2 ()
{
local Pinging
Pinging=$(ping "1ドル" -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '()' ' ')
echo "IP Address = $(awk '{print 2ドル}' <<<"$Pinging")"
echo "Server Name = $(awk '{print 1ドル}' <<<"$Pinging")"
}
for i in "$@"
do
echo "Domain Name = $i"
if nslookup -type=ns "$i" | grep -q 'nameserver.*cloudflare.com'
then
check "$i" || echo "This Domain does not belong to this server."
else
check2 "$i"
fi
whois "$i" | grep "Registrant Name"
nslookup -type=ns "$i" | grep nameserver | awk '{print 2,ドル3,ドル4ドル}'
if curl -sL "http://$i" | grep -q '<title>.*Account.*Suspended'
then
echo "Status = Account Suspended"
else
echo "Status = $(curl -I "$i" 2>/dev/null | head -n 1 | cut -d$' ' -f2-3)"
fi
printf '%*s\n' 100 | tr ' ' '#'
done
@Toby left some room for teamwork :-) Here are some extra points on top of his excellent review.
Naming
Some of the names are very poor, notably check
, check2
and i
as a global variable. i
is perfectly fine as a counter in a counting loop, otherwise not. It would be good to replace all these names with something that describes their purpose.
Also, the convention is to use lowercase names, instead of capitalizing as in Pinging
(which by the way another example of a poor name).
Lastly, names with all capital letters should only be used for system variables or exported variables.
Define constants at the top
It seems this constant defined in check
is quite important for the behavior if the script:
nameserver=('@ns1.ournameserver.com' '@ns2.ournameserver.com' '@ns3.ournameserver.com')
It would be better to define at the top of the script where it's easier to see and modify.
Use $(...)
instead of backticks
The `...`
syntax is obsolete.
Avoid long pipelines when possible. Use $(...)
instead.
Long pipelines with many processes are what slow down shell scripts. It's good to make a habit to avoid them. Take for example:
IPADD=`dig $j $i +noall +answer | grep "A" | awk '{print 5ドル}'`
Here, the grep
process can be easily eliminated, since awk
can perform the same function:
IPADD=$(dig $j $i +noall +answer | awk '/A/ {print 5ドル}')
Furthermore, you use the result to match against a regular expression. Awk can do that too, and probably more efficiently than Bash.
IPADD=$(dig $j $i +noall +answer | awk '/A/ && 5ドル ~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/ {print 5ドル}')
Now in Bash you can simply check if the variable is empty is not.
Iterating over arrays
This is the correct way to iterate over elements of an array:
for item in "${are[@]}"; do ...; done
That is, the double quotes around the array are important, in case the items may contain spaces. Even if you know for sure there won't be spaces in your values, it's good to adopt to writing style so that it becomes a good habit.
Extracting multiple values
This code extracts two values from the output of a command:
Pinging=`ping $i -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '\(|\)' ' '` IPADD=`awk '{print 2ドル}' <<< $Pinging` echo "IP Address = " $IPADD ServerName=`awk '{print 1ドル}' <<< $Pinging` echo "Server Name = " $ServerName
Another way using read
:
read ip servername < <(ping $i -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '\(|\)' ' ' | awk '{ print 2,ドル 1ドル }')
The advantage is one less awk
process.
Note that <(...)
is Bash 4 syntax. If it's not available in your version, then you can save the result of the input process in a variable, and then use a here-string instead.
result=$(ping $i -c 1 | grep 'from' | cut -d$' ' -f4-5| tr '\(|\)' ' ' | awk '{ print 2,ドル 1ドル }')
read ip servername <<< "$result"