4
\$\begingroup\$

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
asked Jul 6, 2018 at 7:52
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

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
answered Jul 6, 2018 at 10:19
\$\endgroup\$
1
\$\begingroup\$

@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"
answered Jul 7, 2018 at 9:36
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.