Bash Script will not recognize function [duplicate] - bash

This question already has answers here:
Calling custom function in bash results in "Command not found" [duplicate]
(1 answer)
Having problems calling function within bash script
(1 answer)
Closed 4 years ago.
I'm trying to create a bash script that will allow you to specify an AWS account that you want to perform some actions in.
I have a variable I need to pass that refers to a file that the script will cycle through.
But the function that performs the actions isn't recognized by the script.
This is the error I get :
./delete_snapshots.sh
What AWS Account:
12345678910
Delete Snapshots in account: AWS Lab
./delete_snapshots.sh: line 14: delete_snapshots: command not found
This is the script :
#!/bin/bash
echo "What AWS Account: ";
read accountnumber
declare -a arr=("12345678910" "109876543212")
for i in "${arr[#]}"
do
if [ "$i" -eq 12345678910 ]; then
aws_account="AWS Lab"
aws_key="lab"
aws_file="aws_lab_snapshots.txt"
echo "Delete Snapshots in account: $aws_account"
delete_snapshots
break
elif [ "$i" -eq 109876543212 ]; then
aws_account="AWS Billing"
aws_key="bill"
aws_file="aws_bill_snapshots.txt"
echo "You are currently in account: $aws_account"
delete_snapshots
break
else
echo "Unkown account"
fi
done
delete_snapshots(){
for i in $(cat $aws_file)
do
echo "*****************************************************************"
echo "deleting snapshot: $i"
aws ec2 delete-snapshot --snapshot-id=$i --profile=lab 2>&1 | sed -e 's/^An error occurred.*when calling the DeleteSnapshot operation: //'
echo "*****************************************************************"
echo; echo; echo; echo; echo
sleep 5
echo "*****************************************************************"
echo "Verify that snapshot: $i is gone:"
aws ec2 describe-snapshots --snapshot-ids=$i --profile=lab 2>&1 | sed -e 's/^An error occurred.*when calling the DescribeSnapshots operation: //g'
echo "*****************************************************************"
echo; echo; echo; echo; echo
done
}
The script works now thanks for some helpful suggestions. Here's the working form of the script:
#!/bin/bash
delete_snapshots(){
for i in $(cat $aws_file)
do
echo "*****************************************************************"
echo "deleting snapshot: $i"
aws ec2 delete-snapshot --snapshot-id=$i --profile=$aws_key 2>&1 | sed -e 's/^An error occurred.*when calling the DeleteSnapshot operation: //'
echo "*****************************************************************"
echo; echo; echo; echo; echo
sleep 5
echo "*****************************************************************"
echo "Verify that snapshot: $i is gone:"
aws ec2 describe-snapshots --snapshot-ids=$i --profile=$aws_key 2>&1 | sed -e 's/^An error occurred.*when calling the DescribeSnapshots operation: //g'
echo "*****************************************************************"
echo; echo; echo; echo; echo
done
}
echo "What AWS Account: ";
read accountnumber
declare -a arr=("123456789101" "109876543212")
for i in "${arr[#]}"
do
if [ "$i" -eq 123456789101 ]; then
aws_account="AWS Lab"
aws_key="lab"
aws_file="source_files/aws_lab_snapshots.txt"
echo "Delete Snapshots in account: $aws_account"
delete_snapshots
break
elif [ "$i" -eq 109876543212 ]; then
aws_account="AWS Billing"
aws_key="bill"
aws_file="source_files/aws_bill_snapshots.txt"
echo "You are currently in account: $aws_account"
delete_snapshots
break
else
echo "Unkown account"
fi
done

Related

Syntax error near unexpected token `done' - Shell Scripting

#!/bin/sh
VAR2=0
while [ $VAR2 -eq 0 ]: do
echo "Please choose one of the following options:"
echo "1. List the current running processes"
echo "2. Check the available free memory"
echo "3. List the disks/partitions"
echo "4. Check for hardware (PCI)"
echo "5. Check for package installation"
echo "6. Create multiple files"
echo "7. Remove multiple files"
echo "8. List the contents of the current directory"
echo "0. Exit"
read VAR1
if [ $VAR1 -eq 0 ]; then
VAR2=2
fi
if [ $VAR1 -eq 1 ]; then
$(top)
fi
if [ $VAR1 -eq 2 ]; then
$(free)
fi
if [ $VAR1 -eq 3 ]; then
$(df)
fi
if [ $VAR1 -eq 4 ]; then
echo "Insert the name of the hardware that you want to search:" read VARHARD $(sudo lspci | grep $VARHARD)
fi
if [ $VAR1 -eq 5 ]; then
echo "Insert the name of the package that you want to search:" read VARPACK $(rpm -qa | grep VARPACK)
fi
if [ $VAR1 -eq 6 ]; then
echo "Insert the base name of the files:" read VARFILE echo "Insert the amount of files you want:" read VARNUMB $(touch $VARFILE{0001..000$VARNUMB})
fi
if [ $VAR1 -eq 7 ]; then
echo "Insert a string to delete all files that contain it:" read VARDEL $(find -type f -name '*$VARDEL*' -exec rm {} \;)
fi
if [ $VAR1 -eq 8 ]; then
$(ls -la)
fi
echo "Press any key and enter to continue... "
read teste
done
So, when I try to run the script "sh script.sh", it gives me an error that says "Syntax error near unexpected token `token'"
Can someone explain the error to me please? I'm new on scripting.
Thanks!
You have two problems in your code, the first is the invocation of subshells where is not due (using $() ) and the second is a typo at the line 26 (you have if instead of fi). The following corrected code works:
#!/bin/bash
VAR2=0
while [ $VAR2 -eq 0 ]; do
echo "Please choose one of the following options:"
echo "1. List the current running processes"
echo "2. Check the available free memory"
echo "3. List the disks/partitions"
echo "4. Check for hardware (PCI)"
echo "5. Check for package installation"
echo "6. Create multiple files"
echo "7. Remove multiple files"
echo "8. List the contents of the current directory"
echo "0. Exit"
read VAR1
if [ $VAR1 -eq 0 ]; then
VAR2=2
fi
if [ $VAR1 -eq 1 ]; then
top
fi
if [ $VAR1 -eq 2 ]; then
free
fi
if [ $VAR1 -eq 3 ]; then
df
fi
if [ $VAR1 -eq 4 ]; then
echo "Insert the name of the hardware that you want to search:"
read VARHARD
sudo lspci | grep $VARHARD
fi
if [ $VAR1 -eq 5 ]; then
echo "Insert the name of the package that you want to search:"
read VARPACK
rpm -qa | grep VARPACK
fi
if [ $VAR1 -eq 6 ]; then
echo "Insert the base name of the files:"
read VARFILE
echo "Insert the amount of files you want:"
read VARNUMB
touch $VARFILE{0001..000$VARNUMB
fi
if [ $VAR1 -eq 7 ]; then
echo "Insert a string to delete all files that contain it:"
read VARDEL
find -type f -name '*$VARDEL*' -exec rm {} \;
fi
if [ $VAR1 -eq 8 ]; then
ls -la
fi
echo "Press any key and enter to continue... "
read teste
done
Why are you using the syntax $(top)? That will execute top to completion (it may be long running, and never end), and then evaluate the output as a command and attempt to execute it. Most likely, the output of top is not valid shell syntax. I'm not sure exactly which command is generating the syntax error related to token, but that's probably the source of your error. Instead of $(top), just write top. Same for all the other instances of $() in the script.

Can anyone suggest why my code for postgresql walarchiveclean up is not working...I give two arguments as parameters but still it does not go forward

This is the code for wal archive clean up in postgresql. I am passing archive path and age before when wal needs to be cleaned up. Its a wrapper scrip but somehow its not working. Whenever I pass arguments it throws first message for passing correct parameters even though I am giving correct one.
#!/bin/bash
if [ "$#" -ne 2 ]; then
echo -e "This script helps in cleaning up archived log files in postgres. Give the command with parameters in order\t
sh walarchivecleanup.sh -p archivepath -a age (days) "
echo "Usage : walarchivecleanup.sh -p archivepath -a age"
echo -e "\t -p <value> -- Path to the archived WAL logs (e.g. /pg_data/pg_xlog/archive)"
echo -e "\t -a <value> -- Age of archived logs to keep (days), anything older will be deleted"
exit 1
else
echo -e "Do Nothing"
fi
archivepath=$1
age=$2
##########################################################
while getopts "p:a" opt;
do
case ${opt} in
p) archivepath=${OPTARG};;
a) age=${OPTARG};;
\? )
echo "Usage: sh walarchivecleanup.sh -p archivepath -a age (days) "
;;
esac
done
###############################################################
if [[ -z $archivepath ]]; then echo "Error: Missing archivepath"; exit 1; fi
if [[ -z $age ]]; then echo "Error: Age (-a) must be given"; exit 1; fi
if ! [[ -d $archivepath ]]; then
echo "Error: archivepath not found"; exit 1
else
cmd_path=$archivepath
fi
if [[ -n $archivecleanup ]]; then
if ! [[ -x $archivecleanup ]]; then
echo "Error: Command $archivecleanup not found or no permission to execute"; exit 1;
else
cmd_command="$archivecleanup"
fi
else
if ! `which pg_archivecleanup 1>/dev/null`; then echo "Error: Command pg_archivecleanup not found"; exit 1; fi
cmd_command="pg_archivecleanup"
fi
if [[ -n $age ]]; then
cmd_file="$(find ${archivepath}/ -type f -mtime +${age} -printf "%C# %f\n" |sort -n | tail -n 1 | awk '{print $NF}')"
else
cmd_file="$archivefile"
fi
execute="$cmd_command $cmd_path $cmd_file"
`$execute`
exit $?
echo "Unknown Error - Should never reach this part"
exit 1

getting error when running my bash script

I made this bash script but getting this error when running it: ./admin2.sh: line 78: syntax error near unexpected token else'
./admin2.sh: line 78:else'.
I've edited it many times but i cant seem to find what exactly the error is. this is the script:
#!/bin/bash
if [[ $key == 1029127 ]]
clear
echo -e ""
echo -e -n "${LIGHTRED}[!] ${WHITE}Loading admin menu"
spinner () {
local SP_WIDTH="$3"
local SP_DELAY="$4"
local SP_STRING=${2:-"'|/=\'"}
local SP_COLOR=0
tput civis
while [ -d /proc/$1 ]; do
((RANDOM%2 == 0)) && SP_COLOR=3$((RANDOM%8)) ||
SP_COLOR=9$((RANDOM%8))
printf "\e[1;${SP_COLOR}m\e7 %${SP_WIDTH}s \e8\e[0m" "$SP_STRING"
sleep ${SP_DELAY:-.2}
SP_STRING=${SP_STRING#"${SP_STRING%?}"}${SP_STRING%?}
done
tput cnorm
}
sleep 2.5 &
spinner "$!" '-\\|/' '1.1' '.2'
tput civis
sleep 1
tput cnorm
while true
do
clear
echo -e "${LIGHTCYAN} Welcome"
echo -e ""
echo -e -n "${WHITE}- Current IP:${LIGHTRED} "
w|awk '{if(NR>2){print $3}}' $3
echo -e -n "${WHITE}- Users connected:${LIGHTRED} "
users | wc -w
echo -e "${WHITE}- Admin privileges:${WHITE
[${LIGHTGREEN}Enabled${WHITE}]"
echo -e ""
echo -e "${LIGHTRED} //Announcements//"
echo -e ""
echo -e "${YELLOW}- Type: /help to see commands"
echo -e "\n"
echo -e ""
echo -e ""
echo -e -n "${LIGHTRED}Type: \c"
read answer
else
echo -e ""
echo -e "${LIGHTRED}[!] ${WHITE}Incorrect key, access denied.
fi
You also seem to have forgotten to end the second while loop. You should end it by adding a doneon the line before the else
...
read answer
done
else
echo -e ""
echo -e "${LIGHTRED}[!] ${WHITE}Incorrect key, access denied.
fi
You're missing a then after your if statement on line 2:
if [[ $key == 1029127 ]]
then
...
else
...
fi
Many people prefer to put the then on the same line, as:
if [[ $key == 1029127 ]]; then
...
else
...
fi
Either way I'd encourage you to properly indent your code so that it's easier to read, and be consistent about style choices such as putting then and do on separate lines or not.

Bash Variable losing its value - strange

notice the FTP_PUT_RETVAL. There are two echo commands, the first one shows a value of '0'. The second one shows no value at all. I am running this inside a nightly cron. BASH is GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
My script tells me that the ftp upload was unsuccessful, because FTP_PUT_RETVAL contains no value!
Why is this occuring? How can I change this? What have I done wrong?
#!/bin/sh
#
# Filename: rh5-manager-cron.sh
#
# Purpose: Runs backup.cron, and FTP uploads backup to Linux4
#
# Usage: the program is run with no arguments. This program is
# intended to run from manager cron, and redirection is handled inside the cron
# e.g. 00 1 * * * /u2/app/lbin/rh5-manager-cron.sh > /tmp/log/rh5-manager-cron.log 2>&1
trap signalCaught ABRT EXIT HUP INT PIPE TERM QUIT
signalCaught () {
for file in $FTP_LOG_FILE $TMPF; do
$BIN_HOME/rm_file $TMPF
done
exit
}
if [[ ! -r /u2/conf/ctrl/lettus.sh || ! -r /u2/app/lbin/fsh_sh_lib ]]; then
printf "Cannot source environment.\n" >&2
exit 1
fi
. /u2/conf/ctrl/lettus.sh
. /u2/app/lbin/fsh_sh_lib
#-------------------------------------------------------
# Variables
#-------------------------------------------------------
PRG=${0##*/}
FTPUSER=dummy
FTPPASS=dummy
FTPHOST=192.168.0.3
BACKUPDIR=/backup
FTPBACKUPNAME=Redhat5Backup.tgz
FTPBACKUPFILE=$BACKUPDIR/$FTPBACKUPNAME
LOGDIR=/tmp/log
FTP_LOG_FILE=$LOGDIR/Redhat5FTP.log
SENDLOGS=$C/sendlogs.dat
ZOOT_XML=$C/zoot.xml
TMPF=`mktemp` || exit 1
#-------------------------------------------------------
# Sanity
#-------------------------------------------------------
if ! isValidUser root manager; then
printf "$PRG: Must be run as user 'root' or user 'manager'.\n" >&2
exit 1
fi
if [[ ! -d $BACKUPDIR ]]; then
logger "$PRG: $BACKUPDIR: Not a valid directory" >&2
exit 1
fi
if [[ ! -d $LOGDIR ]]; then
logger "$PRG: $LOGDIR: Not a valid directory" >&2
exit 1
fi
if [[ ! -r $SENDLOGS || ! -r $ZOOT_XML ]]; then
logger "$PRG: E-mail: Files are not readable: $SENDLOGS, $ZOOT_XML" >&2
exit 1
fi
if ! which lftp >/dev/null 2>&1; then
logger "$PRG: lftp: command not found" >&2
exit 1
fi
# e-mail
EMAIL_SUBJECT="Redhat5 FTP PUT"
EMAIL_TO=$(email_to $SENDLOGS)
EMAIL_FROM=$(email_from $ZOOT_XML)
# ftp binary
LFTP_BIN=$(which lftp 2>/dev/null)
#-------------------------------------------------------
# Functions
#-------------------------------------------------------
# calls lftp to upload a file to server non-interactively
ftp_put() {
$LFTP_BIN $LFTP_DEBUG -u ${FTPUSER},${FTPPASS} $FTPHOST <<-EOF
put $FTPBACKUPFILE
pwd
ls $FTPBACKUPNAME
quit
EOF
#^^^^^^^^^^^ leave the above indentation alone
}
main() {
# Backup, and send manager logs
logger "Running backup.cron..."
echo
backup.cron
BACKUP_CRON_RETVAL=$?
logger "Running fsh_sendlogs..."
echo
$SH_HOME/fsh_sendlogs 1
# show ls listing
logger "Here comes a directory listing..."
echo
/bin/ls -l /backup/Redhat5Backup.tgz
echo
# ftp upload
logger "Running ftp upload..."
echo
ftp_put
FTP_PUT_RETVAL=$?
echo " -- debug: Line ${LINENO:-}: FTP_PUT_RETVAL=${FTP_PUT_RETVAL:-}"
}
checkSuccess() {
if [[ "$BACKUP_CRON_RETVAL" -eq 0 ]]; then
echo "Backup was successful."
echo
echo "*********************************"
echo " OK: Backup was successful."
echo "*********************************"
echo
else
echo "ERROR: Backup FAILED! "
echo
echo "*********************************"
echo " ERROR: Backup FAILED! "
echo "*********************************"
echo
fi
echo " -- debug: Line ${LINENO:-}: FTP_PUT_RETVAL=${FTP_PUT_RETVAL:-}"
if [ "$FTP_PUT_RETVAL" -eq 0 ]; then
echo "lftp: ftp file upload complete."
echo
echo "*********************************"
echo " OK: ftp file upload complete."
echo "*********************************"
echo
else
echo "lftp: error ftp file upload not successful."
echo
echo "*********************************"
echo " ERROR: file upload"
echo " NOT successful."
echo "*********************************"
echo
fi
}
email_logs() {
if [[ -z "$EMAIL_FROM" || -z $EMAIL_TO || -z $EMAIL_SUBJECT || ! -r $FTP_LOG_FILE ]]; then
logger "$PRG: One of the variables is not correctly configured" >&2
exit 1
fi
fsh_mail -r "${EMAIL_TO}" -F "${EMAIL_FROM}" -s "${EMAIL_SUBJECT}" -t "${FTP_LOG_FILE}"
return
}
#----------------------------------------------------------------------
# Main Program
#----------------------------------------------------------------------
main | tee $FTP_LOG_FILE
checkSuccess | tee -a $FTP_LOG_FILE $TMPF
cat $FTP_LOG_FILE >> $TMPF
# E-mail ftp log file
logger "Emailing ftp logfile"
echo
email_logs
#eof
The problem is that you are using:
main | tee $FTP_LOG_FILE
checkSuccess | tee -a $FTP_LOG_FILE $TMPF
Because of the piping, the work done in main is done in a sub-shell, and a sub-shell cannot set variables in the parent shell. So, when checkSuccess (which is also run in a sub-shell) goes to look at the results, it sees what was in the parent shell (nothing), rather than what was set in the main function in a sub-shell.
If you dropped the piping, it would start to work.
More reliably, put the call to checkSuccess into the main function. Or use one or the other of these two notations:
{ main; checkSuccess; } | tee $FTP_LOG_FILE $TMPF
( main; checkSuccess ) | tee $FTP_LOG_FILE $TMPF
Note that the { ... } notation requires a semi-colon after the second function which the ( ... ) notation does not require. However, there is one less process involved in the { ... } mechanism, not that it is going to make any measurable difference to the overall performance of this (the FTP time will dominate).

Validate Emails with Bash

I try to validate an email with a shell script. Is there a easy example to validate a mail? Asked google but just found crap and PHP (also crap..).
Thanks and regards.
If you explicitly state bash on the #! line, you can uses regexes:
#!/bin/bash
if [[ $email =~ '(.+)#(.+)' ]] ; then
user=${BASH_REMATCH[1]}
host=${BASH_REMATCH[2]}
fi
If you are serious about programing with bash, read the man page all the way through. Twice. Also read the Bash FAQ.
Validate script.
The meaning of this script, is to be sure from all emails that are valid or not before sending them email.
this script check a list of emails.
#!/bin/bash
#:
#: e-mail.verify.sh
#:
#: Date: 2011/14/12 13:14 PM IST
#: Author: Louay _at_ louie.msh#gmail.com
#: Discription: Verify (or) Validate the Hotmail Adresses.
#:
#:
#: First we create a Expect script to be sourced for us.
if [ ! $# == 1 ]
then
echo "Invalid Args $0 Filename"
exit 0
fi
#: Verifying the Hotmail adressess.
#: First verify the network Connections
C_R="\e[01;31m" ## Colors
C_B="\e[01;30m"
C_G="\e[01;32m"
C_END="\e[00m"
SMTPSERV=`host -t mx hotmail.com |grep 5 | grep mx2.hotmail.com |cut -d " " -f 7| sed 's/\.$//'`
ping -c2 $SMTPSERV >/dev/null
if [ "$?" -eq 0 ]
then
echo -e "Internet Connection" "\t\t\t\t\t\t$C_G[ OK ]$C_END"
echo -e "$SMTPSERV is AVAILABLE."
echo -n "Verifing"
for (( i=0; i<5; i++ ))
do
echo -n ".."
sleep 1
done
echo
else
echo -e "Internet Connection:" "\t\t\t\t\t\t$C_R[ FAIL ]$C_END" ""
echo -e "$SMTPSERV is Unavialable."
echo -e "Check your Network settings."
exit 0
fi
COUNT=0
RM_FILE="validemails.txt"
rm -f $RM_FILE
cat $1 | while read LINE; do
{
MAFR="MAIL FROM: <louie.msh#gmail.COM>"
MATO="RCPT TO: <$LINE>"
#: ^variablies declared for not get escaped in the next cat command, where
#: we set the $MAFR in the expect script.
cat << __EOF > e-veri
#!/bin/expect
#:
#: Date: 2011/14/12 01:14 PM
#: Author: Louay Mshelim_at_ louie.msh#gmail.com
#: Discription: Expect Script to Verify/Validate the Hotmail Adresses.
#:
set VMAFR "$MAFR"
set VMATO "$MATO"
spawn nc -C mx4.hotmail.com 25
expect "Sending"
send "HELO mx4.hotmail.com\r"
expect "OK"
send "\$VMAFR\r"
expect "OK"
send "\$VMATO\r"
expect "250"
send "quit\r"
expect eof
__EOF
#: Running the expect script and extracting the Results.txt
expect e-veri > Results.txt
grep 550 Results.txt >/dev/null
if [ "$?" -eq 0 ]
then
echo -e $LINE >> invalid.txt #invalid E-mails
else
echo -e "$LINE" >> validemails.txt
fi
}
done
echo -e "Valid E-mail have been saved to $C_R[ validemails.txt ]$C_END"
#: END
Here is an improved and working version of the script by codevour:
#!/bin/bash
# check for valid usage
if [ x$1 = 'x' ]
then
echo "Usage: $0 <email address>"
exit 1
fi
mailcmd=`mktemp`
# grabbing fields
user=`echo $1 | perl -p -e 's/^([^#]+)#([^\#]+)$/$1/g'`
host=`echo $1 | perl -p -e 's/^([^#]+)#([^\#]+)$/$2/g'`
mxhost=`host -t mx $host|perl -p -e 's/.* ([^ ]+)\.$/$1/g'|sort -R|tail -1`
# compose email commands
echo -ne "helo example.com\r\n" > $mailcmd
echo -ne "mail from: <tester#example.com>\r\n" >> $mailcmd
echo -ne "rcpt to: <$1>\r\n" >> $mailcmd
echo -ne "quit\r\n" >> $mailcmd
# check for mail results
mailresult=`cat $mailcmd | nc $mxhost 25| grep ^550 | wc -c`
if [ $mailresult -eq 0 ]
then
echo $1 "is valid"
exit 0
else
echo $1 "is not valid"
exit 1
fi
# clean up
rm $mailcmd
You mean something like this?
#!/bin/bash
# check for valid usage
if [ x$1 = 'x' ]
then
echo "Usage: $0 <email address>"
exit 1
fi
# grabbing fields
user=`echo $1 | cut -f1 -d\#`
host=`echo $1 | cut -f2 -d\#`
mxhost=`host -t mx $host | cut -f7 -d\ `
len=`echo $mxhost | wc -c`
len=`expr $len - 2`
mxhost=`echo $mxhost | cut -b1 -$len`
# compose email commands
echo -ne "helo test.com\r\n" > mailcmd
echo -ne "mail from: test\#test.com\r\n" >> mailcmd
echo -ne "rcpt to: $1\r\n" >> mailcmd
echo -ne "quit\r\n" >> mailcmd
# check for mail results
mailresult=`cat mailcmd | nc $mxhost 25| grep ^550 | wc -c`
if [ $mailresult -eq 0 ]
then
echo $1 "is valid"
exit 0
else
echo $1 "is not valid"
exit 1
fi
# clean up
rm mailcmd
Found at:
Fun things in Life - Simple Bash Email Validator
My any suggestion for the latter script, check work with multiple servers that accept checks without authentication, using nslookup who knows:
For example code in:
http://www.vivaolinux.com.br/script/Simples-Verificador-de-Email-Gmail
see the code below in the site.
I hope I have contributed and I hope to collaborate as well.
Thank you.
You can use like this,
read emailId
if echo "${emailId}" | grep '^[a-zA-Z0-9]*#[a-zA-Z0-9]*\.[a-zA-Z0-9]*$' >/dev/null; then
echo Valid
else
echo Not Valid
fi

Resources