I am writing a bash script that you can run on a server where mediawikis of games are deployed. I want to check if the wikis use SMTP. So a part of my script greps for the content in the config file that proves that they use SMTP.
The problem is, that I do that on multiple servers and I want to loop through multiple markets on a server. Not all servers share the same market names. In my script I have arrays that contain ALL market names. I want my script to account for the case that the grep cant find the file in which it is to look up if SMTP is used. How can I go about that?
I was thinking about a extra command to ask if the file exists before grepping. But that didn't work out as you can
for i in "${markets[#]}"; do
myPATH="/www/${game}_$i/${game}_$i/LocalSettings.php"
grepOut="grep -q 'wgSMTP = array(' "$myPATH""
if grep -q "wgSMTP = array(" "$myPATH"; then
echo -e "The Market ${BLUE}$i${NC} ${GREEN}uses${NC} SMTP."
else
if [[ "$grepOut" == *"No such file or directory"* ]]; then
if [[ "$market" == "all" ]]; then
echo -e "All markets:"
else
echo -e "The Market ${BLUE}$i doesn't${NC} exist on this server."
fi
else
echo -e "The Market ${BLUE}$i${NC} ${RED}doesn't${NC} use SMTP."
fi
fi
done
for i in "${markets[#]}"; do
path="/www/${game}_$i/${game}_$i/LocalSettings.php"
if ! [[ -f "$path" ]]; then
if [[ "$market" == "all" ]]; then
echo -e "All markets:"
else
echo -e "The Market ${BLUE}$i doesn't${NC} exist on this server."
fi
continue
fi
if grep -q 'wgSMTP = array(' "$path"; then
echo -e "The Market ${BLUE}$i${NC} ${GREEN}uses${NC} SMTP."
else
echo -e "The Market ${BLUE}$i${NC} ${RED}doesn't${NC} use SMTP."
fi
done
Not sure if $market should be $i (or vice versa).
Related
I am trying to make it so I can use a upper or lower case as the variable read.
here is my code that I did. This is meant to select the model of the server and run the right install file based on the input
#!/bin/bash
clear
dir=" "
# ============================================================================
# Set the Product Name
# ============================================================================
MODEL="UNKNOWN"
while [ "$1" = "UNKNOWN" ]; do
KIND="UNKNOWN"
echo -n "Enter kind [HPCLD|HBCB]: "
read KIND
UPPER="$(echo ${KIND}|tr 'a-z' 'A-Z')"
case "$UPPER" in
HPCLD) MODEL="HPCLD" ;;
HBCB) MODEL="HBCB" ;;
esac
done
if [ "$1" == "HPCLD" ]; then
echo "Preparing to installation HPCLD applications...."
cd hpcld
dir="$(pwd)"
echo $dir
echo "./install_hpcld.sh"
else
echo "Preparing to installation HBCB applications...."
cd hbcb
dir="$(pwd)"
echo $dir
echo "./install_hbcb.sh"
fi
The main reason it isn't working is that you wrote "$1" instead of "$MODEL" on the while statement.
This question already has answers here:
Check Whether a User Exists
(19 answers)
Closed 4 years ago.
I'm making a script that add an user, deletes an user and change password of an user passed as parameter ($1). I want to check if the user exists, so I can control this better. I know this question have been asked a lot of times, I've been googling this before, but really, these solutions didn't work for me, I don't know which is my mistake, so sorry.
This is my code:
#!/bin/bash
existe=$(grep -c '^$1:' /etc/passwd)
if [ $existe -eq 0 ]; then
echo "The user $1 exists"
echo ""
else
echo "The user $1 does not exist"
echo ""
fi
I've tried the ">/dev/null" solution, the "getent" thing... Agh...
No matter what I do, the user always exists, and the code I pasted here is the last one I was trying.
Can you help me? ^^ Thanks in advance.
you need double quotes for variable substituation, and your test condition is wrong:
exists=$(grep -c "^$1:" /etc/passwd)
if [ $exists -eq 0 ]; then
echo "The user $1 does not exist"
else
echo "The user $1 exists"
fi
besides, you may use id(1).
You can also just use grep's return value for this:
if grep -q "^$1:" /etc/passwd; then
printf 'The user %s exists\n' "$1"
else
printf 'The user %s does not exist\n' "$1"
fi
or, probably better, using getent
if getent passwd "$1" >/dev/null; then
printf 'The user %s exists\n' "$1"
else
printf 'The user %s does not exist\n' "$1"
fi
so if you don't actually need the count, you needn't try to save the count and check it later. The exit codes of the commands themselves will tell you if it was found or not.
You can use grep to act as the conditional
#!/bin/sh
grep -q "^$1:" /etc/passwd && echo exists || echo FALSE
or if you like your imperative conditionals in blocks
#!/bin/sh
if grep -q "^$1:" /etc/passwd ;then
echo exists
else
echo FALSE
fi
(Both tested with bash and dash).
Wrote a Bash script to create two files, each with a list of dates, to be used later. The script requires three parameters: a data subject, a minimum date, and a maximum date. Here's my script:
#!/bin/sh
dataSubj=$1
minDate=$2
maxDate=$3
echo -e "my variables:\nsubject:\t$dataSubj\nstart:\t$minDate\nend:\t$maxDate"
//Wrote the above line for debugging
configDir=/opt/site1/ETL/MFGEDW/config/MERS2
dateCount=1
addTime=00:00:00
fromDates=$dataSubj_fromDates.txt
toDates=$dataSubj_toDates.txt
cd $configDir
echo "Creating fromDates file and adding $minDate"
echo -e "$minDate $addTime" > ./$fromDates
echo "Creating toDates file"
>./$toDates
while [[ $minDate < $maxDate ]]
do
minDate=$(date -d "$minDate 7 days" +%Y-%m-%d)
((dateCount++))
if [[ $minDate < $maxDate ]]; then
echo "Adding $minDate to fromDates file"
echo -e "$minDate $addTime," >> ./$fromDates
fi
echo "Adding $minDate to toDates file"
echo -e "$minDate $addTime," >> ./$toDates
echo "$dateCount dates total"
done
exit $dateCount
My issue is that instead of having two files with the desired dates, I have one hidden file with all the dates that should have been written in the two files. I'm fairly new to scripting, but modeled this after other scripts that I've used and know work. Is there something I'm missing or added unnecessarily? Thanks in advance.
This is your problem:
fromDates=$dataSubj_fromDates.txt
toDates=$dataSubj_toDates.txt
Bash doesn't know you mean dataSubj is the name of the variable. You're trying to use two different variables:
dataSubj_fromDates
dataSubj_toDates
Pretty sure those don't exist. Note '.' is a stopper for variable naming. Try using:
fromDates=${dataSubj}_fromDates.txt
toDates=${dataSubj}_toDates.txt
Next time print all variables when debugging.
I am trying to do the following in bash:
get my external IP
read first line of a file
compare both values
if it is not the same, delete the file and recreate it with the current address
I really don't know why this fails, all my script does is to output my current address and the first line of the file (which by the way is simply "asd" for testing)
#!/bin/bash
IP= curl http://ipecho.net/plain
OLD= head -n 1 /Users/emse/Downloads/IP/IP.txt
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
$IP> /Users/emse/Downloads/IP/IP.txt
exit
fi
Some obvious problems in your script:
Don't put spaces on either side of equal sign if you want to do assignment
You want the output of curl, head so wrap them in backticks (`)
You want to write $IP into the file, not to execute the content of it as a command, so echo it
The script becomes:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
echo $IP > /Users/emse/Downloads/IP/IP.txt
exit
fi
Excellent answer qingbo, just a tad bit of refinement:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" != "$OLD" ]; then
echo $IP > /Users/emse/Downloads/IP/IP.txt # > creates/truncates/replaces IP.txt
fi
I would like to have the echo command executed when cat /etc/passwd | grep "sysa" is not true.
What am I doing wrong?
if ! [ $(cat /etc/passwd | grep "sysa") ]; then
echo "ERROR - The user sysa could not be looked up"
exit 2
fi
try
if ! grep -q sysa /etc/passwd ; then
grep returns true if it finds the search target, and false if it doesn't.
So NOT false (! false) == true.
if evaluation in shells are designed to be very flexible, and many times doesn't require chains of commands (as you have written).
Also, looking at your code as is, your use of the $( ... ) form of cmd-substitution is to be commended, but think about what is coming out of the process. Try echo $(cat /etc/passwd | grep "sysa") to see what I mean. You can take that further by using the -c (count) option to grep and then do if ! [ $(grep -c "sysa" /etc/passwd) -eq 0 ] ; then which works but is rather old school.
BUT, you could use the newest shell features (arithmetic evaluation) like
if ! (( $(grep -c "sysa" /etc/passwd) == 0 )) ; then ...`
which also gives you the benefit of using the c-lang based comparison operators, ==,<,>,>=,<=,% and maybe a few others.
In this case, per a comment by Orwellophile, the arithmetic evaluation can be pared down even further, like
if ! (( $(grep -c "sysa" /etc/passwd) )) ; then ....
OR
if (( ! $(grep -c "sysa" /etc/passwd) )) ; then ....
Finally, there is an award called the Useless Use of Cat (UUOC). :-) Some people will jump up and down and cry gothca! I'll just say that grep can take a file name on its cmd-line, so why invoke extra processes and pipe constructions when you don't have to? ;-)
I hope this helps.
I think it can be simplified into:
grep sysa /etc/passwd || {
echo "ERROR - The user sysa could not be looked up"
exit 2
}
or in a single command line
$ grep sysa /etc/passwd || { echo "ERROR - The user sysa could not be looked up"; exit 2; }
This one
if [[ ! $(cat /etc/passwd | grep "sysa") ]]; then
echo " something"
exit 2
fi
What am I doing wrong?
$(...) holds the value, not the exit status, that is why this approach is wrong. However, in this specific case, it does indeed work because sysa will be printed which makes the test statement come true. However, if ! [ $(true) ]; then echo false; fi would always print false because the true command does not write anything to stdout (even though the exit code is 0). That is why it needs to be rephrased to if ! grep ...; then.
An alternative would be cat /etc/passwd | grep "sysa" || echo error. Edit: As Alex pointed out, cat is useless here: grep "sysa" /etc/passwd || echo error.
Found the other answers rather confusing, hope this helps someone.
Here is an answer by way of example:
In order to make sure data loggers are online a cron script runs every 15 minutes that looks like this:
#!/bin/bash
#
if ! ping -c 1 SOLAR &>/dev/null
then
echo "SUBJECT: SOLAR is not responding to ping" | ssmtp abc#def.com
echo "SOLAR is not responding to ping" | ssmtp 4151112222#txt.att.com
else
echo "SOLAR is up"
fi
#
if ! ping -c 1 OUTSIDE &>/dev/null
then
echo "SUBJECT: OUTSIDE is not responding to ping" | ssmtp abc#def.com
echo "OUTSIDE is not responding to ping" | ssmtp 4151112222#txt.att.com
else
echo "OUTSIDE is up"
fi
#
...and so on for each data logger that you can see in the montage
at http://www.SDsolarBlog.com/montage
FYI, using &>/dev/null redirects all output from the command, including errors, to /dev/null
(The conditional only requires the exit status of the ping command)
Also FYI, note that since cron jobs run as root there is no need to use sudo ping in a cron script.
simply:
if ! examplecommand arg1 arg2 ...; then
#code block
fi
without any brackets.
On Unix systems that supports it (not macOS it seems):
if getent passwd "$username" >/dev/null; then
printf 'User %s exists\n' "$username"
else
printf 'User %s does not exist\n' "$username"
fi
This has the advantage that it will query any directory service that may be in use (YP/NIS or LDAP etc.) and the local password database file.
The issue with grep -q "$username" /etc/passwd is that it will give a false positive when there is no such user, but something else matches the pattern. This could happen if there is a partial or exact match somewhere else in the file.
For example, in my passwd file, there is a line saying
build:*:21:21:base and xenocara build:/var/empty:/bin/ksh
This would provoke a valid match on things like cara and enoc etc., even though there are no such users on my system.
For a grep solution to be correct, you will need to properly parse the /etc/passwd file:
if cut -d ':' -f 1 /etc/passwd | grep -qxF "$username"; then
# found
else
# not found
fi
... or any other similar test against the first of the :-delimited fields.
I'd expect to see in the answers the direct use of grep with -q option (as we don't care the result but need only the return code.)
if ! grep -qs "sysa" /etc/passwd; then
echo "ERROR - The user sysa could not be looked up" >&2
exit 2
fi
or (to use chained execution on fail)
grep -qs "sysa" /etc/passwd || {
echo "ERROR - The user sysa could not be looked up" >&2
exit 2
}
Better, because the opposite is wanted, there's option -v for that
if grep -qsv "sysa" /etc/passwd; then
echo "ERROR - The user sysa could not be looked up" >&2
exit 2
fi
or (to use chained execution on success)
grep -qsv "sysa" /etc/passwd && {
echo "ERROR - The user sysa could not be looked up" >&2
exit 2
}
Notes
I like redirecting error messages to stderr, but echo output to stdout, hence >&2
Taylor the search pattern, e.g something like '^sysa:' if it's full login.