Eroor in my shell script

Hello,

I am sorry for my dump question. I am really new to shell scripting and still learning. I tried to add the if then else to my script but since I added it, I am always getting an error. Can someone have a look at it and tell my what I have done wrong?

Target: If the output of “whois”, “whois2”, “whois3” is empty it should be replaced with text, otherwise it should take the value. All has to be written into an output.

  • ----start script------

> #!/bin/bash
> # Bulk Domain Lookup
> #
> # File name/path of domain list:
> domain_list='domains.txt' # One FQDN per line in file.
> #
> # IP address of the nameserver used for lookups:
> ns_ip='8.8.8.8' # Is using Google NS
> #
> # Seconds to wait between lookups:
> loop_wait='1' 
> 
> echo "Domain;Registrar;Country;Owner"; #Headers
> for domain in `cat $domain_list`
> do
>    ns=`dig ns $domain |sed -ne '16p'`; #nameserver lookup & use only line 16 from output
>         ip=`dig @$ns_ip +short $domain |tail -n1`; # IP address lookup
>                 mx=`dig mx $domain +short`; #mailserver lookup & use only line 11 from output
>                         whois=`whois $domain |grep -i "Registrar:" | tail -n 1`;
>                         whois2=`whois $domain |grep -i "Registrant Country:" | tail -n 1`;
>                         whois3=`whois $domain |grep -i "Registrant Organization:" | tail -n 1`;
>         if [ -z "$whois" -eq ""];
>                 then echo "No Data";
>                         elif [echo $whois];
>         if [ -z "$whois2" -eq ""];
>                 then echo "No Data";
>                         elif [echo $whois2];
>         if [ -z "$whois3" -eq ""];
>                 then echo "No Data";
>                         elif [echo $whois3];
> echo "$domain;$whois;$whois2;whois3;$ns;$ip;mx;"; #Output order
> 
>    sleep $loop_wait # Pause before the next lookup to avoid flooding NS
> done;
> ------end script------

Upfront, thank you for your help!!

Greetings,

N16htSh1ft

Apart from your Forum syntax error where your code is prefixed with > , you’re using the if statements wrong:

  1. The [ and ] must have a space on both sides (unless it’s a semicolon or the start of a line), which you’re failing to do for the latter.
  2. The test brackets mentioned above contain syntax errors: you’re using the -z (empty string) flag while also using the numerical -eq (equals) comparator. Those are mutually exclusive. Of note, you probly wanna use ! instead of -z to test for zero-length string, and not use any flags at all instead of -n to test for a non-zero-length string, like so: [ "${foo}" ]. Those make it easier to memorize them.
  3. The elif statement is a massive syntax error: the code has the same problem as the number 1 mentioned above, you’re using the statement to print the var, and is also missing the then part.
  4. You’re not terminating the if statement with fi.
  5. The final echo statement is missing the dollar signs for the var refs for whois3 and mx
  6. While you can use for loop for this purpose, it’s a massive bad practice, you should use a while loop while redirecting its input like outlined behind the link in the 2nd part of the Correct code section.

EDIT: I noticed you did terminate the for loop. My eyes were deceived by the missing indentation of the last echo line.

Thank you very much for the information. Of course the original code doesn’t has the prefix - I used it here in the forum as I do not know how to enter the code without having text formats interpreted (e.g. # will do an H1).

I will try to correct my issues based on your great detailed description.

Again, thank you very much!

You’ll wanna make use of ShellCheck, either the website or as a plugin for VS Code (VS Codium), for instance. It’ll catch a massive amount of errors, and allow a quick access to the wiki documentation of theirs where it’s explained further :wink:

Good recommendation! Thank you! As I am really new and just started with it, I exactly need such tips. And perfect that you have not corrected my script and only guided me to the massive errors.

I did fix (and format) the code in VS Codium to the point it ain’t a syntax error fest, but the point about the for loop needing replacing with while still stands.

Also if you’re only using Bash and not intending to make the code portable between Linux distros and over to Mac or something, then you can use $(...) instead of the backticks

`...`

for process substitution since you can nest commands, and it’s easier to read.

Here on the Forum you can use the same for code as I did above by placing 3 backticks on its own line, optionally the code type right after, like bash for Bash, then on a new line the code itself, and close with 3 backticks on its own line.

Here’s the code:

#!/bin/bash
# Bulk Domain Lookup
#
# File name/path of domain list:
domain_list='domains.txt' # One FQDN per line in file.
#
# IP address of the nameserver used for lookups:
ns_ip='8.8.8.8' # Is using Google NS
#
# Seconds to wait between lookups:
loop_wait='1' 

echo "Domain;Registrar;Country;Owner"; #Headers
for domain in `cat $domain_list`; do
    ns=`dig ns $domain | sed -ne '16p'`; #nameserver lookup & use only line 16 from output
    ip=`dig @$ns_ip +short $domain | tail -n1`; # IP address lookup
    mx=`dig mx $domain +short`; #mailserver lookup & use only line 11 from output
    whois=`whois $domain | grep -i "Registrar:" | tail -n 1`;
    whois2=`whois $domain | grep -i "Registrant Country:" | tail -n 1`;
    whois3=`whois $domain | grep -i "Registrant Organization:" | tail -n 1`;
    if [ ! "$whois" ]; then
        echo "No Data";
    else
        echo $whois;
    fi

    if [ ! "$whois2" ]; then
        echo "No Data";
    else
        echo $whois2;
    fi

    if [ ! "$whois3" ]; then
        echo "No Data";
    else
        echo $whois3;
    fi

    echo "$domain;$whois;$whois2;$whois3;$ns;$ip;$mx;"; #Output order

    sleep $loop_wait # Pause before the next lookup to avoid flooding NS
done

Ahh nice. I needed to look off a little bit of the if else part but I believe I have the rest of the errors solved. You are awsome! Thank you! :hugs:

#!/bin/bash
# Bulk DNS Lookup
# Generates a CSV seperated by ";" of lookups from a list of domains.
#
# File name/path of domain list:
#domain_list='domains.txt' # One FQDN per line in file.
#
# IP address of the nameserver used for lookups:
ns_ip='8.8.8.8' # Is using Google NS
#
# Seconds to wait between lookups:
loop_wait='0.5' # Is set to 1

echo "Domain;Registrar;Country;Owner;NS;MX;IP"; #Headers
while read -r domain in "$domains_list"
do
   ns=$("dig ns $domain |sed -ne '16p'"); #nameserver lookup & use only line 16 from output
        ip=$("dig @$ns_ip +short $domain |tail -n1"); # IP address lookup
                mx=$("dig mx $domain +short"); #mailserver lookup & use only line 11 from output
                        whois=$("whois $domain |grep -i 'Registrar:' | tail -n 1");
                        whois2=$("whois $domain |grep -i 'Registrant Country:' | tail -n 1");
                        whois3=$("whois $domain |grep -i 'Registrant Organization:' | tail -n 1");
        if [ ! "$whois" ]; then
                echo "No Data";
        else
                echo "$whois";
        fi

        if [ ! "$whois2" ]; then
                echo "No Data";
        else
                echo "$whois2";
        fi

        if [ ! "$whois3" ]; then
                echo "No Data";
        else
                echo "$whois3";
        fi
echo "$domain;$whois;$whois2;$whois3;$ns;$mx,$ip"; #Output order

   sleep $loop_wait # Pause before the next lookup to avoid flooding NS
done;

You’re going the right direction, but that code’s still non-functional, as worded by ShellCheck:

  1. while read -r domain in "$domains_list": This does not read 'domains_list'. Remove $/${} for that, or use ${var?} to quiet. https://github.com/koalaman/shellcheck/wiki/SC2229
    ^ However, that error is unhelpful in this case cuz the statement itself is illegal (AFAIK), it needs to be
while read -r domain; do
    #the code here
done <<< "$domains_list"

FYI: the <<< "${foo}" syntax is called a Here String, which redirects the double-quoted contents of ${foo} to the input of the loop or a process. This saves opening another process and thus a pipe, so you’ll avoid doing unnecessities such as echo "${foo}" | while or

wget -O - 'http://example.com' | while
  1. The ${domains_list} used in the while is unset, meaning it doesn’t exist. Also, when you do create ${domains_list}, you need to know what’s used as the domain separator, and make the code act accordingly. If it’s just a space, nothing needs to be changed for that.
  2. If you totally quote process substitutions inside $(...) you’re actually introducing a form of syntax error in that the shell thinks you’re giving it a command name that consists of various chars. I assume you concluded this as the solution to double-quoting var refs. For ex, this is the correct code for the ns=$(...):
ns=$(dig ns "${domain}" |sed -ne '16p')

This is cuz var assignments implicitly double-quotes the resulting contents, but var refs inside the assignment, like in these process substitutions, must be double-quoted separately.

For ex, this is what happened when I tried a similar code:

$ _aaa=$("ls -1")
-bash: ls -1: command not found
$ _aaa=$(ls -1)
$ echo "${_aaa}"
foobar
testfolder

Linux sysadmin blog - Linux/Unix Howtos and Tutorials - Linux bash shell scripting wiki