I am new to shell programming. I have two files:
eg.txt
file.sh
The eg.txt file has some HTML content and file.sh cotains a shell script.
In the script a value is assigned to the temp variable, and that value should be injected into the HTML file.
eg.txt
<html>
Hi MGM ,<br/>
One alert has been received !!<br/>
Here is the event Data.<br/><br/>
<font size=‘1’>{temp}</font>
<br/><br/>
Regards,
WDTS Supports.
</html>
file.sh
echo $1
temp=56
(
echo "To:"$1
echo "Subject: Alert Updates !! "
echo "Content-Type: text/html"
echo cat eg.txt
) | /usr/sbin/sendmail -t
echo "Mail sent !!"
With sed :
sed "s/{temp}/$temp/" eg.txt | /usr/sbin/sendmail -t
You can also use printf to inject variables in your template :
file.sh
temp=56
tpl=$(cat "eg.txt")
printf "$tpl" "$1" "$temp" | /usr/sbin/sendmail -t
eg.txt
To:%s
Subject: Alert Updates !!
Content-Type: text/html
<html>
Hi MGM ,<br/>
One alert has been received !!<br/>
Here is the event Data.<br/><br/>
<font size=‘1’>%s</font>
<br/><br/>
Regards,
WDTS Supports.
</html>
Update:
If multiple variables, just write multiple substitute commands (and update placeholders in eg.txt):
sed "s/{temp1}/$temp1/;s/{temp2}/$temp2/" eg.txt | /usr/sbin/sendmail -t
I have introduced some error checking to your code :
#!/bin/bash
temp=56
if [ -z "$1" ]
then
echo "Usage : ./file.sh user_name_to_mail to"
exit -1
else
if id "$1" >/dev/null 2>&1 #Check if user exists, suppress stdout, stderr
then
mail_header=$(echo -e "To: $1\nSubject: Alert Updates"'!!'"\nContent-Type: text/html\n")
mail_body=$(awk -v var="$temp" '{print gensub(/{temp}/,var,"g"$0)}' eg.txt)
echo -e "$mail_header\n$mail_body" | sendmail -t
else
echo -e "Sorry! Invalid User\n"
exit -1 # The error code is set to detect failure
fi
fi
To prevent the mails going to spam you need to have a valid SPF record for domain from which you're sending email. Check [ this ] for a starting point.
Note:
! is a special character to bash, it is used to refer to previous command. To work around this problem I have used ..Updates"'!!'"\nContent-Type...
Inside the single quotes the ! loses its special meaning.
Interesting reads :
What is an [ SPF ] record?
Open SPF [ documentation ] .
echo $1
temp=56
(
echo "To:"$1
echo "Subject: Alert Updates !! "
echo "Content-Type: text/html"
awk -F "" -v var=$temp '{gsub(/{temp}/,var,$0); print}' < eg.txt
) | /usr/sbin/sendmail -t
echo "Mail sent !!"
added awk to '|' where the temp is stored in awk variable : var which is later replaced
awk -F "" -v var=$temp '{gsub(/{temp}/,var,$0); print}'
Related
I'm building a bash script to send an email based off the last command. I seem to be having difficulties. Outside of a script the command works fine but when putting it in script it doesn't give the desired outcome.
Here is snippet of script:
grep -vFxf /path/to/first/file /path/to/second/file > /path/to/output/file.txt
if [ -s file.txt ] || echo "file is empty";
then
swaks -t "1#email.com" -f "norply#email.com" --header "Subject: sample" --body "Empty"
else
swaks -t "1#email.com" -f "norply#email.com" --header "subject: sample" --body "Not Empty"
fi
I ran the commands outside of script and I can see that there is data but when I add the commands within script I get the empty output. Please advise . Thank you in advance .
Your condition will always be true, because if [ -s file.txt ] fails, the exit status of the ||-list is the exit status of echo, which is almost guaranteed to be 0. You want to move the echo out of the condition and into the body of the if statement. (And to simplify further, just set the body to a variable and call swaks after the if completes.
if [ -s file.txt ];
then
body="Not Empty"
else
echo "file is empty"
body="Empty"
fi
swaks -t "1#email.com" -f "norply#email.com" --header "subject: sample" --body "$body"
If the only reason you create file.txt is to check if it is empty or not, you can just put the grep command directly in the if condition:
if grep -vFxfq /atph/to/first/file /path/to/second/file; then
body="Not Empty"
else
echo "No output"
body="Empty"
fi
swaks -t "1#email.com" -f "norply#email.com" --header "subject: sample" --body "$body"
This question already has answers here:
How to parse a CSV file in Bash?
(6 answers)
How to send email from Terminal?
(8 answers)
Closed 5 years ago.
enter code hereI have text file which contains the following:
#MailTo ESC BCC ESC Subject ESC Message Body
user1#example.com|||user1#xyz.com|||Subject1|||Message Body1
user2#example.com|||user2#xyz.com|||Subject2 |||Message Body2
user3#example.com|||user3#xyz.com|||Subject3|||Message Body3
user4#example.com|||user4#xyz.com|||Subject4|||Message Body4
user5#example.com|||user5#xyz.com|||Subject5|||Message Body5
user6#example.com|||user6#xyz.com|||Subject6|||Message Body6
user7#example.com|||user7#xyz.com|||Subject7|||Message Body7
usern#example.com|||usern#xyz.com|||Subjectn|||Message Bodyn
Please note that I am using "ESC" pattern as a delimiter between the fields ( I don't use ";" as a delimiter to avoid any conflicts in the Message body if ";" exists in the message body) so i think i can't parse it as a csv file.
please advice, how to create a bash script to parse this file to send emails to different users with different subject, and different message body, please?
Here is my suggested solution for my question (I replaced "ESC" word with "|||" as a delimiter):
#!/bin/bash
# Functions
function is_valid_email
{
pattern='^[a-zA-Z0-9._-]\+#[a-zA-Z0-9]\+\.[a-z]\{2,\}'
echo "$1" | grep "$pattern" > /dev/null
}
# read file line by line
COUNTER=0
while read -r line
do
# check if we are one the first line or not which contains heading
if [ ! $COUNTER -eq 0 ]; then
# we are not in the first line so we may continue
# extract variables from the line
TO=$(echo $line | awk -F '\\|\\|\\|' '{print $3}');
CC=$(echo $line | awk -F '\\|\\|\\|' '{print $4}');
BCC=$(echo $line | awk -F '\\|\\|\\|' '{print $5}');
SUBJECT=$(echo $line | awk -F '\\|\\|\\|' '{print $6}');
BODY=$(echo $line | awk -F '\\|\\|\\|' '{print $7}');
COMMAND="echo \"$BODY\" | mail -s \"$SUBJECT\" "
# check if CC is a valid email
is_valid_email "$CC"
if [ "$?" -ne 0 ]; then
echo "TODO: handle invliad cc email ($CC)"
else
COMMAND_CC=" -c \"$CC\""
COMMAND=$COMMAND$COMMAND_CC
fi
# check if BCC is a valid email
is_valid_email "$BCC"
if [ $? != 0 ]; then
echo "TODO: handle invliad bcc email ($BCC)"
else
COMMAND_BCC=" -b \"$BCC\""
COMMAND=$COMMAND$COMMAND_BCC
fi
# check if TO is a valid email
is_valid_email "$TO"
if [ "$?" -ne 0 ]; then
echo "TODO: handle invliad to email ($TO)"
else
COMMAND_TO=" \"$TO\""
COMMAND=$COMMAND$COMMAND_TO
fi
eval $COMMAND
else
# we are on the first line so increase the counter and continue
COUNTER=$((COUNTER+1))
fi
done < test_file
I created .sh file to grep specific words in log and will send a mail to particular emailID (Set Cronjob to run this script every 1hour). Its working as expected, But the Problem is if there is no error also I am getting Empty Mail.
Needs to get Mail, if we caught error and DBError file has content. Kindly please help me on this to resolve this issue.
#!/bin/bash
if [ ! -e DBErrors ] ; then
grep "sqlException" /opt/apps/cms/logs/cms-runtime.log > DBErrors
mail -s "ALERT: sqlException" Jayaram.Ponnusamy#gmail.com < DBErrors
else
comm -23 <(grep "sqlException" /opt/apps/cms/logs/cms-runtime.log) DBErrors | mail -s "ALERT: sqlException" Jayaram.Ponnusamy#gmail.com
grep "sqlException" /opt/apps/cms/logs/cms-runtime.log > DBErrors
fi
Thanks
Jayaram
Could you try this;
#!/bin/bash
dbErrors="/tmp/DBErrors"
if [ ! -e "$dbErrors" ]; then
grep "sqlException" /opt/apps/cms/logs/cms-runtime.log > $dbErrors
mailbody=$(grep "sqlException" /opt/apps/cms/logs/cms-runtime.log); [[ -n "$mailbody" ]] && mail -s "ALERT: sqlException" Jayaram.Ponnusamy#gmail.com
else
mailbody=$(comm -23 <(grep "sqlException" /opt/apps/cms/logs/cms-runtime.log| sort -n) <(sort -n "$dbErrors")); [[ -n "$mailbody" ]] && mail -s "ALERT: sqlException" Jayaram.Ponnusamy#gmail.com
grep "sqlException" /opt/apps/cms/logs/cms-runtime.log > $dbErrors
fi
I was trying to make a script that would pretty much automate this process:
http://knowledgelayer.softlayer.com/procedure/add-additional-ips-redhat
Wasn't too sure how well it would work, but didn't get too far before I could get the script to one. Below is the content of the script:
Editing with updated code:
Edit#2: Got it mostly working, however now it runs the loop and skips over the read propmt to get the static IP
#!/bin/bash
path=/etc/sysconfig/network-scripts/
echo "Let's get your IP added :)"
echo""
getnewip()
{
echo read -p "Enter the new IP Address you wish to add: " staticip
}
getserverinfo()
{
gateway=$(netstat -rn | sed -n 3p | awk '{print $2}')
netmask=$(ifconfig eth1 | grep -i 'netmask' | grep -v '127.0.0.1' | awk '{print $4}')
clone=$( ifconfig | grep eth1 | awk '{print $1}' | cut -d: -f2 )
}
rangechecks()
{
cd /etc/sysconfig/network-scripts/
ls ifcfg-eth1-range*
filename==$1
if [[ ! -f $filename ]]; then
touch "$filename"
echo "Created \"$filename\""
fi
digit=1
while true; do
temp_name=$filename-$digit
if [[ ! -f temp_name ]]; then
touch "$temp_name"
echo "Created $path\"$temp_name\""
digit=$((digit + 1 ))
fi
done
}
writeinterfacefile()
{
cat >> "/etc/sysconfig/network-scripts/$1" << EOF
IPADDR_START=$staticip
IPADDR_END=$staticip
NETMASK=$netmask
CLONENUM_START=$((clone+1))
EOF
echo ""
echo "Your information was saved in the file '$1'."
echo ""
}
{
clear
getserverinfo
echo ""
echo "Please verify this information: "
echo "Gateway Address: " "$gateway"
echo "Netmask: " "$netmask"
echo "Your new IP: " "$staticip"
echo ''
while true; do
read -p "Is this information correct? [y/N]" yn
case $yn in
[Yy]* ) $writeinterfacefile;;
[Nn]* ) print "$getserverinfo" && exit ;;
* ) echo 'Please enter Y or n';;
esac
done
}
I'm fairly new at scripting, so excuse the horrid syntax. My eye is on that EOF but I have no clue.
rangecheckshas no }, your while has no done...
You should indent your code. I started doing that, and noticed the error right away.
Other things:
Single quotes don't expand variables, '/etc/sysconfig/network-scripts//$1 won't do what you want it to.
echo "" is equivalent to echo.
foo='bar'; echo "blah" echo -n $foo will output 'blah echo -n bar'.
exit exits the script, I'm not sure that's what you think it does.
[y/N] usually means N by default (the capital letter).
Also, you then ask to enter Y or n. Be consistent!
When using a variable as a parameter, double quote it. This ensures it stays the way it is (as one parameter, and not expanded by the shell).
I can't see the closing curly brace of function rangechecks
Also, don't indent the shebang in the first line.
This question already has answers here:
Sending a mail from a linux shell script
(11 answers)
Closed 5 years ago.
I am on linux machine and I monitor a process usage. Most of the time I will be away from my system and I have access to internet on my device. So I planned to write a shell-script that can mail me the output of the process.
Is it possible?
If so how to make a shell-script send me mail?
Please provide a snippet to get started.
Yes it works fine and is commonly used:
$ echo "hello world" | mail -s "a subject" someone#somewhere.com
Basically there's a program to accomplish that, called "mail". The subject of the email can be specified with a -s and a list of address with -t. You can write the text on your own with the echo command:
echo "This will go into the body of the mail." | mail -s "Hello world" you#youremail.com
or get it from other files too:
mail -s "Hello world" you#youremailid.com < /home/calvin/application.log
mail doesn't support the sending of attachments, but Mutt does:
echo "Sending an attachment." | mutt -a file.zip -s "attachment" target#email.com
Note that Mutt's much more complete than mail.
You can find better explanation here
PS: thanks to #slhck who pointed out that my previous answer was awful. ;)
sendmail works for me on the mac (10.6.8)
echo "Hello" | sendmail -f my#email.com my#email.com
mail -s "Your Subject" your#email.com < /file/with/mail/content
(/file/with/mail/content should be a plaintext file, not a file attachment or an image, etc)
#!/bin/sh
#set -x
LANG=fr_FR
# ARG
FROM="foo#bar.com"
TO="foo#bar.com"
SUBJECT="test é"
MSG="BODY éé"
FILES="fic1.pdf fic2.pdf"
# http://fr.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions
SUB_CHARSET=$(echo ${SUBJECT} | file -bi - | cut -d"=" -f2)
SUB_B64=$(echo ${SUBJECT} | uuencode --base64 - | tail -n+2 | head -n+1)
NB_FILES=$(echo ${FILES} | wc -w)
NB=0
cat <<EOF | /usr/sbin/sendmail -t
From: ${FROM}
To: ${TO}
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=frontier
Subject: =?${SUB_CHARSET}?B?${SUB_B64}?=
--frontier
Content-Type: $(echo ${MSG} | file -bi -)
Content-Transfer-Encoding: 7bit
${MSG}
$(test $NB_FILES -eq 0 && echo "--frontier--" || echo "--frontier")
$(for file in ${FILES} ; do
let NB=${NB}+1
FILE_NAME="$(basename $file)"
echo "Content-Type: $(file -bi $file); name=\"${FILE_NAME}\""
echo "Content-Transfer-Encoding: base64"
echo "Content-Disposition: attachment; filename=\"${FILE_NAME}\""
#echo ""
uuencode --base64 ${file} ${FILE_NAME}
test ${NB} -eq ${NB_FILES} && echo "--frontier--" || echo
"--frontier"
done)
EOF
Well, the easiest solution would of course be to pipe the output into mail:
vs#lambda:~$ cat test.sh
sleep 3 && echo test | mail -s test your#address
vs#lambda:~$ nohup sh test.sh
nohup: ignoring input and appending output to `nohup.out'
I guess sh test.sh & will do just as fine normally.
top -b -n 1 | mail -s "any subject" your_email#domain.com