Send e-mail using command line and save IP rules - shell

I am coding a script to select some IPs from a table in a DB, and then use IPTables rules to ban theses IPs, last step is to notify by e-mail, but I am getting 2 errors:
#!/bin/bash
Now=$(date +"%d-%m-%Y %T")
fileLocation="/var/lib/mysql/DBName/"
fileName="ip2ban.txt"
filePath=$fileLocation$fileName
curLocation=$(pwd)
#Connect to DB and select ban_ip
mysql -u root -pPASSWORD -D DBName -e 'SELECT ip INTO OUTFILE "'$filePath'" FROM ban_ip WHERE ip_tables = "0"' >> banIP.log 2>&1
selRes=$?
# If the command was successful
if [ $selRes -eq "0" ]
then
# We need to check if the file exists on the saved location
#find $fileLocation -type f -iname "ip2ban.txt" -empty => To check if file empty or not
if [ -f $filePath ]
then
mv $filePath $curLocation'/ip2ban.txt'
# Connect to DB and update the ban_ip
mysql -u root -pPASSWORD -D DBName -e 'UPDATE ban_ip SET ip_tables = "1" WHERE ip_tables = "0"' >> banIP.log 2>&1
upRes=$?
if [ $upRes -eq "0" ]
then
# Send message for succesful result
echo -e "Database updated with new banned IPs on $Now \nThank you for using this script" 2>&1 | sed '1!b;s/^/To: myID#gmail.com\nSubject: New banned IPs[Success]\n\n/' | sendmail -t
else
# Send message for failure result
echo -e "We cannot update the ban_ip table on $Now \nThank you for using this script" 2>&1 | sed '1!b;s/^/To: myID#gmail.com\nSubject: [Failure] New banned IPs\n\n/' | sendmail -t
fi
fi
else
echo 'Something wrong with Select statment on' $Now >> banIP.log
fi
# Save IPTables rules
iptables-save > /root/Scripts/IPTables/BannedIPs.conf // LIGNE 53
I am getting 2 errors:
line 53: iptables-save: command not found
line 37: sendmail: command not found
However the sendamil is already installed, with mail, postfix:
# which sendmail
/usr/sbin/sendmail
# which mail
/usr/bin/mail
# which postfix
/usr/sbin/postfix
Thanks for your usual support

According to the crontab(5) man page for Linux:
PATH is set to "/usr/bin:/bin".
Meaning your shell script will not be able to find anything under /usr/sbin or /sbin. Change this with by adding the following near the top of your script:
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
Also the environment can be set from within the crontab. See https://stackoverflow.com/a/14694543/5766144 for how to do this.

Related

Running cql statements with shell script

I have a below shell script which reads a file and updates the table. But the problem with the below code is that a connection is established for running each sql statements. I am looking for recommendation to enhance this code.
#!/bin/bash
input="/Users/temp/newfile.txt"
while IFS= read -r var
do
echo "update keyspace.tableName set randomColumn='randomText' where random_id='$var'; exit" | ./cqlsh serverName -u username -p password
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select random_id,randomColumn from keyspace.tableName where random_id='$var'; exit" | ./cqlsh serverName -u username -p password
else
echo FAIL
fi
done < "$input"
I suggest doing this with the Python driver if you'd like better performance.
This example should be roughly equivalent:
#! /usr/bin/env python3
from cassandra.cluster import Cluster
from cassandra.auth import PlainTextAuthProvider
cluster = Cluster(auth_provider=PlainTextAuthProvider(username='cassandra', password='cassandra'))
session = cluster.connect()
with open("/Users/temp/newfile.txt") as f:
for line in f:
try:
rows = session.execute("UPDATE keyspace.tableName SET randomColumn='randomText' WHERE random_id=%(var)s", {'var'=line})
print("SUCCESS")
for r in rows:
print(r)
except Exception:
print("FAIL")
edit: you can even go a step further and use prepared statements and async queries, which will provide very significant performance increases if you are making a large volume of queries.
cqlsh has a -f option which allows to run cql statement from a file. You could generate the cql statements by parsing your newfile.txt and then run cqlsh with -f option
At the very basic level, you could do something like this:
#!/bin/bash
input="newfile.txt"
while IFS= read -r var
do
echo "update ks.t1 set name='randomText' where id=$var;" >> result
done < "$input"
./cqlsh serverName -u username -p password -f result
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select * from keyspace.tableName; exit" | ./cqlsh serverName -u username -p password
else
echo FAIL
fi
I suggest to use cqlsh -e with xargs :
#!/bin/bash
input="/Users/temp/newfile.txt"
while IFS= read -r var
do
echo "update keyspace.tableName set randomColumn='randomText' where random_id='$var';" | xargs cqlsh serverName -u 'username' -p 'password' -e
if [ $? -eq 0 ]; then
echo SUCCESS
echo "select random_id,randomColumn from keyspace.tableName where random_id='$var';" | xargs cqlsh serverName -u 'username' -p 'password' -e
else
echo FAIL
fi
done < "$input"

My Bash script won't cache an item

I'm trying to use a Bash script I found and have slightly modified to automatically update the DNS settings on GoDaddy.
It sort of works, however I'm not getting the echo "no ip address, program exit" because I don't think on line 28 the cache file is being created. Would anybody be able to tell me what's going on? I'm using Raspbian. Many thanks in advance!
#/bin/bash
# This script is used to check and update your GoDaddy DNS server to the IP address of your current internet connection.
#
# Original PowerShell script by mfox: https://github.com/markafox/GoDaddy_Powershell_DDNS
# Ported to bash by sanctus
# Added AAAA record by Binny Chan
#
# Improved to take command line arguments and output information for log files by pollito
#
# First go to GoDaddy developer site to create a developer account and get your key and secret
#
# https://developer.godaddy.com/getstarted
#
# Be aware that there are 2 types of key and secret - one for the test server and one for the production server
# Get a key and secret for the production server
# Check an A record and a domain are both specified on the command line.
if [ $# -ne 2 ]; then
echo "usage: $0 type a_record domain_name"
echo "usage: $0 AAAA www my_domain"
exit 1
fi
# Set A record and domain to values specified by user
name=$1 # name of A record to update
domain=$2 # name of domain to update
cache=/tmp/.mcsync.$name.$domain.addr
[ -e $cache ] && old=`cat $cache`
# Modify the next two lines with your key and secret
key="key" # key for godaddy developer API
secret="secret" # secret for godaddy developer API
headers="Authorization: sso-key $key:$secret"
#echo $headers
# Get public ip address there are several websites that can do this.
ret=$(curl -s GET "http://ipinfo.io/json")
currentIp=$(echo $ret | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b")
# Check empty ip address or not
if [ -z "$currentIp" ]; then
echo $name"."$domain": $(date): no ip address, program exit"
exit 1
fi
# Check cache ip, if matched, program exit
if [ "$old" = "$currentIp" ]; then
echo $name"."$domain": $(date): address unchanged, program exit $currentIp"
echo "IPs equal. Exiting..."
exit
else
echo $name"."$domain": $(date): currentIp:" $currentIp
fi
#Get dns ip
result=$(curl -s -k -X GET -H "$headers" \
"https://api.godaddy.com/v1/domains/$domain/records/A/$name")
dnsIp=$(echo $result | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b")
echo $name"."$domain": $(date): dnsIp:" $dnsIp
# ip not match
if [ "$dnsIp" != $currentIp ];
then
echo $name"."$domain": $(date): IPs not equal. Updating."
request='{"data":"'$currentIp'","ttl":3600}'
#echo $request
nresult=$(curl -i -k -s -X PUT \
-H "$headers" \
-H "Content-Type: application/json" \
-d $request "https://api.godaddy.com/v1/domains/$domain/records/A/$name")
#echo $nresult
echo $name"."$domain": $(date): IPs not equal. Updated."
fi
No, the message is on line 44, which is written because $currentIp is empty, which is retrieved on line 39: reading the response of curl request to "http://ipinfo.io/json".
otherwise just remove the cache file
rm /tmp/.mcsync.$name.$domain.addr
where $name and $domain are replaced with first and second argument to script.

notify-send from within a bash script

I'd like to use notify-send from within a bash script that is running in the background to inform the user about the progress of the script. More specifically this is a script that automagically runs when a USB flash drive is inserted and runs a scan with ClamAV.
Specifically at line 30 and line 66. So far, I'm not having any luck. Can someone give me some advice/help? Thanks.
#!/bin/bash
#doOnUSBinsert_0.2.sh
#Author : Totti
# Make it executable by running 'sudo chmod x doOnUSBinsert_0.2.sh'
if ! [ -f /etc/udev/rules.d/80-doOnUSBinsert.rules ]
then # rule not added
cp "$0" /usr/bin/doOnUSBinsert
chmod u x /usr/bin/doOnUSBinsert
# echo 'SUBSYSTEM=="usb", ACTION=="add", RUN ="/path/to/script.sh"' | sudo tee /etc/udev/rules.d/80-clamscan.rules
echo 'SUBSYSTEM=="usb", ACTION=="add", RUN ="/usr/bin/doOnUSBinsert & "' | tee /etc/udev/rules.d/80-doOnUSBinsert.rules
if [ $? -eq 0 ]
then
echo 'Rule Successfully added. See file "/usr/bin/doOnUSBinsert" if you wish to edit the command'
exit 0
else
echo 'ERROR while adding rule'
exit 1
fi
fi
lfile="/tmp/doOnUSBinsert.log" # udev
lfile2="/tmp/clamscanFromUdev.log" # clamscan
lfile3="/tmp/doOnUSBinsert_mount.log" # mount
notify-send "USB SCAN ON INSERT" "Currently scanning with ClamAV"
main ()
{
sleep 12 # let the partitions to mount
#cat /proc/$$/environ | tr '�' 'n' >> /tmp/udevEnvirn.txt
echo "found $ID_SERIAL" >> "$lfile"
cat /etc/mtab | grep "^$part_c" >> "$lfile.3"
if [ "$ID_SERIAL"x = 'x' ]
then
echo "Exiting on empty ID_SERIAL" >> "$lfile"
exit 1
fi
#Eg: ID_SERIAL --> /dev/disk/by-id/usb-sandisk....42343254343543
#i=0
echo 'searching partitions' >> "$lfile"
for partitionPath in $( find /dev/disk/by-id/ -name "*$ID_SERIAL*part*" )
do
echo "current partition = $partitionPath" >> "$lfile"
# part[i ]="$( readlink -f "$partition" )" # Eg Output: /dev/sdb1 , /dev/sdb2
part_c="$( readlink -f $partitionPath )"
mpoint="$( cat /etc/mtab | grep "^$part_c" | awk '{print $2}' )"
echo "partitionPath= $partitionPath, part = $part_c, mountpoint= $mpoint" >> "$lfile"
echo "Scaning --> $mpoint" >> "$lfile.2"
############################################
clamscan -r --bell "$mpoint"/* >> "$lfile.2"
#############################################
done
}
notify-send "USB SCAN ON INSERT" "Finished scanning with ClamAV"
main &
echo ______________________________________ >> "$lfile"
exit 0
I'm pretty new to the linux world, but while looking for a solution for a similar project I found THIS
Tip: An overview on the available icons can be found here. To send
desktop notification from a background script running as root (replace
X_user and X_userid with the user and userid running X respectively):
sudo -u X_user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/X_userid/bus notify-send 'Hello world!' 'This is an example notification.'
Hope this will help others.
Depending on how you are running the script it may not have access to the display variable. Try running export DISPLAY=:0.0 prior to the command.
If you are running the script as a different user, ie root, then you may also need to run it as su - <logged in user> -c notify-send ... (I usually don't need to do this, but I remember having to at one point - but I cant recall which distro or version I was on at the time.)

Crontab will not execute .sh but crontab will execute a command

This issue is currently driving me nuts.
I setup a crontab with sudo crontab -e
The contents are 1 * * * * /home/bolte/bin/touchtest.sh
The contents of that file are:
#!/bin/bash
touch /home/bolte/bin/test.log
It creates the file. But the below script will not run.
#!/bin/bash
# CHANGE THESE
auth_email="11111111#live.co.uk"
auth_key="11111111111111111" # found in cloudflare
account settings
zone_name="11111.io"
record_name="11111.bolte.io"
# MAYBE CHANGE THESE
ip=$(curl -s http://ipv4.icanhazip.com)
ip_file="/home/bolte/ip.txt"
id_file="/home/bolte/cloudflare.ids"
log_file="/home/bolte/cloudflare.log"
# LOGGER
log() {
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
}
# SCRIPT START
log "Check Initiated"
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ $ip == $old_ip ]; then
echo "IP has not changed."
exit 0
fi
fi
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d " " -f 1) == 2 ]; then
zone_identifier=$(head -1 $id_file)
record_identifier=$(tail -1 $id_file)
else
zone_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$zone_name" -H "X-Auth-E$
record_identifier=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_record$
echo "$zone_identifier" > $id_file
echo "$record_identifier" >> $id_file
fi
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_ident$
[ Read 55 lines (Warning: No write permission) ]
^G Get Help ^O Write Out ^W Where Is ^K Cut Text ^J Justify ^C Cur Pos ^Y Prev Page
^X Exit ^R Read File ^\ Replace ^U Uncut Text ^T To Linter ^_ Go To Line ^V Next Page
I've been trying to troubleshoot why this code will not run every minute, there doesn't seem to be any output in the same folder as the script, which is located at /home/bolte/cloudflare-update-record.sh
Ok so the answer to this was, I was editing crontab with sudo, and the files were located in my users home folder. This is why they weren't working. Resolved my own issue.
If you have this issue just use $ crontab -e rather than sudo crontab -e, and specify full paths for your file outputs, unless you are putting the proper path variables in your script.

How to run .sh using Cygwin in windows

I have a file named backup.sh, I have installed and set path variable too. but when i double click backup.sh file its saying something which I don't know. scenario is back mongo db database backup using script in grails.
#!/bin/bash
#
# Michael Mottola
# <mikemottola#gmail.com>
# December 18, 2011
#
# Creates backup files (bson) of all MongoDb databases on a given server.
# Default behaviour dumps the mongo database and tars the output into a file
# named after the current date. ex: 2011-12-19.tar.gz
#
### Set server settings
HOST="localhost"
PORT="27017" # default mongoDb port is 27017
USERNAME=""
PASSWORD=""
# Set where database backups will be stored
# keyword DATE gets replaced by the current date, you can use it in either path below
BACKUP_PATH="Desktop/path/to/backup/directory" # do not include trailing slash
FILE_NAME="DATE" #defaults to [currentdate].tar.gz ex: 2011-12-19.tar.gz
##################################################################################
# Should not have to edit below this line unless you require special functionality
# or wish to make improvements to the script
##################################################################################
# Auto detect unix bin paths, enter these manually if script fails to auto detect
MONGO_DUMP_BIN_PATH="$(which mongodump)"
TAR_BIN_PATH="$(which tar)"
# Get todays date to use in filename of backup output
TODAYS_DATE=`date "+%Y-%m-%d"`
# replace DATE with todays date in the backup path
BACKUP_PATH="${BACKUP_PATH//DATE/$TODAYS_DATE}"
# Create BACKUP_PATH directory if it does not exist
[ ! -d $BACKUP_PATH ] && mkdir -p $BACKUP_PATH || :
# Ensure directory exists before dumping to it
if [ -d "$BACKUP_PATH" ]; then
cd $BACKUP_PATH
# initialize temp backup directory
TMP_BACKUP_DIR="mongodb-$TODAYS_DATE"
echo; echo "=> Backing up Mongo Server: $HOST:$PORT"; echo -n ' ';
# run dump on mongoDB
if [ "$USERNAME" != "" -a "$PASSWORD" != "" ]; then
$MONGO_DUMP_BIN_PATH --host $HOST:$PORT -u $USERNAME -p $PASSWORD --out $TMP_BACKUP_DIR >> /dev/null
else
$MONGO_DUMP_BIN_PATH --host $HOST:$PORT --out $TMP_BACKUP_DIR >> /dev/null
fi
# check to see if mongoDb was dumped correctly
if [ -d "$TMP_BACKUP_DIR" ]; then
# if file name is set to nothing then make it todays date
if [ "$FILE_NAME" == "" ]; then
FILE_NAME="$TODAYS_DATE"
fi
# replace DATE with todays date in the filename
FILE_NAME="${FILE_NAME//DATE/$TODAYS_DATE}"
# turn dumped files into a single tar file
$TAR_BIN_PATH --remove-files -czf $FILE_NAME.tar.gz $TMP_BACKUP_DIR >> /dev/null
# verify that the file was created
if [ -f "$FILE_NAME.tar.gz" ]; then
echo "=> Success: `du -sh $FILE_NAME.tar.gz`"; echo;
# forcely remove if files still exist and tar was made successfully
# this is done because the --remove-files flag on tar does not always work
if [ -d "$BACKUP_PATH/$TMP_BACKUP_DIR" ]; then
rm -rf "$BACKUP_PATH/$TMP_BACKUP_DIR"
fi
else
echo "!!!=> Failed to create backup file: $BACKUP_PATH/$FILE_NAME.tar.gz"; echo;
fi
else
echo; echo "!!!=> Failed to backup mongoDB"; echo;
fi
else
echo "!!!=> Failed to create backup path: $BACKUP_PATH"
fi
its giving --host command not found. updated for later help.
bash FilePath/backup.sh
For example if you have backup.sh file in E:/SohamShetty/Files then you should do like this.
bash E:/SohamShetty/Files/backup.sh
You can run it as :
bash backup.sh
or
chmod +x backup.sh
./backup.sh

Resources