How to search for multiple domain names availability using bash? - linux

I'm trying to search for multiple domain names availability with this script but it doesn't work, where's the mistake? thanks
#!/bin/bash
WEB=('madmane1' 'madmane2' 'madmane3' 'madmane4' 'madmane5' 'madmane6' 'madmane7' 'madmane8' 'madmane9')
ELEMENTS=${#WEB[#]}
for (( i=0;i<$ELEMENTS;i++)); do
whois ${WEB[${i}]}$'.com' | egrep -q \
'^No match|^NOT FOUND|^Not fo|AVAILABLE|^No Data Fou|has not been regi|No entri'
if [ $? -eq 0 ]; then
echo "${WEB[${i}]}$'.com' : available"
fi
done
here's the error:
line 9: ^No match|^NOT FOUND|^Not fo|AVAILABLE|^No Data Fou|has not been regi|No entri: command not found

Assigning stuff to an array and then wrecking it by assigning it to a string without quoting seems like the main mistake here, though it's not the reason you are getting a syntax error.
You also want to avoid testing ”$?” to see if a command succeeded or not, an anti-pattern
See also Correct Bash and shell script variable capitalization
The reason for the error message seems to be a space after the backslash, so you are escaping the space instead of the newline, and thus the shell (in some sense correctly) parses the next line as a new command.
#!/bin/bash
web=('madmane1' 'madmane2' 'madmane3' 'madmane4' 'madmane5' 'madmane6' 'madmane7' 'madmane8' 'madmane9')
for domain in "${web[#]}"; do
if whois "$domain.com" |
grep -Eq '^No match|^NOT FOUND|^Not fo|AVAILABLE|^No Data Fou|has not been regi|No entri'
then
echo "$domain.com: available"
fi
done
Going forward, probably try http://shellcheck.net/ before asking for human assistance.

I think I fixed the problem with https://www.shellcheck.net/
here it is now:
#!/bin/bash
WEB=('madmane1' 'madmane2' 'madmane3' 'madmane4' 'madmane5' 'madmane6' 'madmane7' 'madmane8' 'madmane9')
ELEMENTS=${#WEB[#]}
for (( i=0;i<$ELEMENTS;i++)); do
whois "${WEB[${i}]}"$'.com' | grep -E \
'^No match|^NOT FOUND|^Not fo|AVAILABLE|^No Data Fou|has not been regi|No entri'
if [ $? -eq 0 ]; then
echo "${WEB[${i}]}$'.com' : available"
fi
done

Related

Mail output with Bash Script

SSH from Host A to a few hosts (only one listed below right now) using the SSH Key I generated and then go to a specific file, grep for a specific word with a date of yesterday .. then I want to email this output to myself.
It is sending an email but it is giving me the command as opposed to the output from the command.
#!/bin/bash
HOST="XXXXXXXXXXXXXXXXXX, XXXXXXXXXXXXX"
DATE=$(date -d "yesterday")
INVALID=' cat /xxx/xxx/xxxxx | grep 'WORD' | sed 's/$/.\n/g' | grep "$DATE"'
COUNT=$(echo "$INVALID" | wc -c)
for x in $HOSTS
do
ssh BLA#"$x" $COUNT
if [ "$COUNT" -gt 1 ];
then
EMAILTEXT=""
if [ "$COUNT" -gt 1 ];
then
EMAILTEXT="$INVALID"
fi
fi
done | echo -e "$EMAILTEXT" | mail XXXXXXXXXXX.com
This isn't properly an attempt to answer your question, but I think you should be aware of some fundamental problems with your code.
INVALID=' cat /xxx/xxx/xxxxx | grep 'WORD' | sed 's/$/.\n/g' | grep "$DATE"'
This assigns a simple string to the variable INVALID. Because of quoting issues, s/$/.\n/g is not quoted at all, and will probably be mangled by the shell. (You cannot nest single quotes -- the first single-quoted string extends from the first quote to the next one, and then WORD is outside of any quotes, followed by the next single-quoted string, etc.)
If your intent is to execute this as a command at this point, you are looking for a command substitution; with the multiple layers of uselessness peeled off, perhaps something like
INVALID=$(sed -n -e '/WORD/!d' -e "/$DATE/s/$/./p" /xxx/xxx/xxxx)
which looks for a line matching WORD and $DATE and prints the match with a dot appended at the end -- I believe that's what your code boils down to, but without further insights into what this code is supposed to do, it's impossible to tell if this is what you actually need.
COUNT=$(echo "$INVALID" | wc -c)
This assigns a number to $COUNT. With your static definition of INVALID, the number will always be 62; but I guess that's not actually what you want here.
for x in $HOSTS
do
ssh BLA#"$x" $COUNT
This attempts to execute that number as a command on a number of remote hosts (except the loop is over HOSTS and the variable containing the hosts is named just HOST). This cannot possibly be useful, unless you have a battery of commands named as natural numbers which do something useful on these remote hosts; but I think it's safe to assume that that is not what is supposed to be going on here (and if it was, it would absolutely be necessary to explain this in your question).
if [ "$COUNT" -gt 1 ];
then
EMAILTEXT=""
if [ "$COUNT" -gt 1 ];
then
EMAILTEXT="$INVALID"
fi
fi
So EMAILTEXT is either an empty string or the value of INVALID. You assigned it to be a static string above, which is probably the source of your immediate question. But even if it was somehow assigned to a command on the local host, why do you need to visit remote hosts and execute something there? Or is your intent actually to execute the command on each remote host and obtain the output?
done | echo -e "$EMAILTEXT" | mail XXXXXXXXXXX.com
Piping into echo makes no sense at all, because it does not read its standard input. You should probably just have a newline after done; though a possibly more useful arrangement would be to have your loop produce output which we then pipe to mail.
Purely speculatively, perhaps something like the following is what you actually want.
for host in $HOSTS; do
ssh BLA#"$host" sed -n -e '/WORD/!d' -e "/$DATE/s/$/./p" /xxx/xxx/xxxx |
grep . || echo INVALID
done | mail XXXXXXXXXXX.com
If you want to check that there is strictly more than one line of output (which is what the -gt 1 suggests) then this may need to be a little bit more complicated.
Your command substitution is not working. You should read up on how it works but here are the problem lines:
COUNT=$(echo "$INVALID" | wc -c)
[...]
ssh BLA#"$x" $COUNT
should be:
COUNT_CMD="'${INVALID} | wc -c'"
[...]
COUNT=$(ssh BLA#"$x" $COUNT_CMD)
This inserts the value of $INVALID into the string, and puts the whole thing in single quotes. The single quotes are necessary for the ssh call so the pipes aren't evaluated in the script but on the remote host. (COUNT is changed to COUNT_CMD for readability/clarity.)
EDIT:
I misread the question and have corrected my answer.

Unmatching parentheses in awk command inside bash script causing syntax error

This is the error I get after compiling and running the file
./skript05.sh: 13: ./skript05.sh: Syntax error: word unexpected (expecting ")")
Here's the important snippet of the code, with line 13 pointed out. I don't think the rest of the code is needed since it works well, but if it is, let me know.
ls -l $1 | awk "
if($1 ~ /-([r-][w-][x-]){3}/)
{
MUCHLINES=$(system(\"egrep -o \"^[a-z ]{1,}$\" \", $9) | wc -l) ;#13
test -z "$MUCHLINES" && continue ;
print $9":"$MUCHLINES ;
>&2 echo "$9":"yes" ;
}
else >&2 echo "$9":"no" ;
"
What I can figure out is that it ignores symbols {} in lines 12 and 17, but I can't figure out why. All other parentheses are not ignored and highlighted properly when editing code in gedit for example.
I'm working on this in Linux.
I've been searching for answers on this for days, but can't seem to find any. If there are any, I'll apologize and delete this question. Thank you for any help!
(In case you need to know what is this code supposed to do — it should print into stdout "(nameoffile):(x)", where x is number of lines made up of only lowercase letters and spaces; and print into stderr "(nameoffile):yes/no" with yes in case of files (in ls -l known by having - as first symbol in access rights).)
#EdW - As others have pointed out, the script that you posted is a jumble, but I thought that the following might be helpful to you in that it does illustrate how one can combine ls, awk, and egrep in a bash script, more or less along the lines you seem to have had in mind. Please note, however, that it does NOT address some of the issues that others have raised, nor is it intended to serve as a model. It probably does not even do precisely what you want, but I hope you find it helpful in achieving some of your goals.
#!/bin/bash
ls -l $1 | awk '{print $1, $9}' | while read mask file
do
if [[ $mask =~ -([r-][w-][x-]){3} ]] ; then
MUCHLINES=$(egrep -o "^[a-z ]{1,}$" "$file" | wc -l)
if [[ $MUCHLINES -gt 0 ]] ; then
echo "$file:" $MUCHLINES
>&2 echo "$file:yes"
else
>&2 echo "$file:no"
fi
fi
done

Delete words from given files with sed

I have this assignment to solve:
"Write a shell script that continuously reads words from the keyboard and
deletes them from all the files given in the command line."
I've tried to solve it, here's my attempt:
#!/bin/bash
echo "Enter words"
while (true)
do
read wrd
if [ "$wrd" != "exit" ]
then
for i in $#
do
sed -i -e 's/$wrd//g' $i
done
else
break
fi
done
This is the error that I receive after introducing the command: ./h84a.sh fisier1.txt
Enter words
suc
sed: can't read 1: No such file or directory
Sorry if I'm not very specific, it's my first time posting in here. I'm working in a terminal on Linux Mint which is installed on another partition of my PC. Please help me with my problem. Thanks!
I think you can simplify your script quite a lot:
#!/bin/bash
echo "Enter words"
while read -r wrd
do
[ "$wrd" = exit ] && break
sed -i "s/$wrd//g" "$#"
done
Some key changes:
The double quotes around the sed command are essential, as shell variables are not expanded within single quotes
Instead of using a loop, it is possible to pass all of the file names to sed at once, using "$#"
read -r is almost always what you want to use
I would suggest that you take care with in-place editing using the -i switch. In some versions of sed, you can specify the suffix of a backup file like -i.bak, so the original file is not lost.
In case you're not familiar with the syntax [ "$wrd" = exit ] && break, it is functionally equivalent to:
if [ "$wrd" = exit ]
then break
fi
$# expands to the number of arguments (so 1 in this case)
You probably meant to use $* or "$#"

if statement in while loop bash

I am trying to make script that inserts hostname and ip address for certain website in mysql , but before the script inserts results i want to check if they already exist and if it does the script should not insert it.
result_check=$(mysql -uroot -p123qwe webs -e "SELECT COUNT(*) AS NUMBER FROM webs WHERE hostname='$hostname' AND ip='$ip'";)
cat $dir/webs | while read hostname ip; do
if [[ $result_check -eq 0 ]]; then
echo "INSERT INTO webs (hostname,ip) VALUES ('$hostname','$ip');"
fi;
done | mysql -uroot -p123qwe webs;
And this somehow does not work , i can think of other way to get the job done(without if) but i want to make it this way.
My webs file looks like that :
somedomain.com 192.168.3.3 ... and etc.
This is the error i get:
line 23: [[: NUMBER
0: syntax error in expression (error token is "0")
I have tried many ways to escape this error (changing the brackets from [[ to (( ) but i've had no luck.
The error message suggests that the output from the first mysql begins with NUMBER. Maybe there's a way to suppress column headers? Ah yes, the -N option.
Secondly, you appear to require the values that are being read from the file to be present in the query, so you have to rearrange things accordingly.
Additionally, you want to clean up the syntax.
while read hostname ip; do
result_check=$(mysql -N -uroot -p123qwe webs \
-e "SELECT COUNT(*) AS NUMBER FROM webs WHERE hostname='$hostname' AND ip='$ip'")
if [[ $result_check -eq 0 ]]; then
echo "INSERT INTO webs (hostname,ip) VALUES ('$hostname','$ip');"
fi
done <"$dir"/webs | mysql -uroot -p123qwe webs
I dislike the temporary variable for the result_check but inlining it would hamper readability, so I guess it'll have to stay.
However, a much better approach would be to use native SQL constructs for INSERT ... WHERE NOT EXISTS or similar. See also How to 'insert if not exists' in MySQL?
Your code is kosher, so $result_check is clearly not a number. Here are some suggestions:
Add an echo if [[ $result_check -eq 0 ]] before the if check to see what's being checked.
In Bash it's sometimes helpful to protect against strings being empty. In this case, the protection would be: if [[ "x$result_check" = x0 ]], but you can't do any interesting integer stuff with that check, for example testing equality for "0" and "00" would fail. if [[ "0$result_check" -eq 0 ]] should solve that problem, but I haven't tested it. On my system, the [[ function actually handles the empty string with no problem, so [[ $undefined_variable -eq 0 ]] is always true.
You can run type [[ to see what the [[ function actually is. For me, it's a shell keyword (bash version 3.2).
For fun, try the [ function instead. As long as you use quotes and add a prefix to protect against empty variables, the result should be the same for these simple tests.

Search log file for string with bash script

I just started learning PHP. I'm following phpacademy's tutorials which I would recommend to anyone. Anyways, I'm using XAMPP to test out my scripts. I'm trying to write a bash script that will start XAMPP and then open firefox to the localhost page if it finds a specific string, "XAMPP for Linux started.", that has been redirected from the terminal to the file xampp.log. I'm having a problem searching the file. I keep getting a:
grep: for: No such file or directory
I know the file exists, I think my syntax is wrong. This is what I've got so far:
loaded=$false
string="XAMPP for Linux started."
echo "Starting Xampp..."
sudo /opt/lampp/lampp start 2>&1 > ~/Documents/xampp.log
sleep 15
if grep -q $string ~/Documents/xampp.log; then
$loaded=$true
echo -e "\nXampp successfully started!"
fi
if [$loaded -eq $true]; then
echo -e "Opening localhost..."
firefox "http://localhost/"
else
echo -e "\nXampp failed to start."
echo -e "\nHere's what went wrong:\n"
cat ~/Documents/xampp.log
fi
In shell scripts you shouldn't write $variable, since that will do word expansion on the variable's value. In your case, it results in four words.
Always use quotes around the variables, like this:
grep -e "$string" file...
The -e is necessary when the string might start with a dash, and the quotes around the string keep it as one word.
By the way: when you write shell programs, the first line should be set -eu. This enables *e*rror checking and checks for *u*ndefined variables, which will be useful in your case. For more details, read the Bash manual.
You are searching for a string you should put wihtin quotes.
Try "$string" instead of $string
There are a couple of problems:
quote variables if you want to pass them as a simple argument "$string"
there is no $true and $false
bash does variable expansion, it substitutes variable names with their values before executing the command. $loaded=$true should be loaded=true.
you need spaces and usually quotes in the if: if [$loaded -eq $true] if [ "$loaded" -eq true ]. in this case the variable is set so it won't cause problems but in general don't rely on that.

Resources