I am trying to nest multiple if-statements as the following:
#!/bin/bash
# start_server.sh
#
# Use this script to start the MarketDataTransmitter.
#
# Usage: ./start_server.sh Starts the MarketDataTransmitter.
reset=$(tput sgr0)
red=$(tput setaf 1)
green=$(tput setaf 2)
yellow=$(tput setaf 3)
cyan=$(tput setaf 6)
echo
directory=$(ls -l)
check_exist=$(awk -v a="$directory" -v b="MarketDataTransmitter" 'BEGIN { print index(a, b) }')
if [ "$check_exist" = "0" ]; then
# MarketDataTransmitter is not present.
echo "${red}[ERROR]${reset} Could not start ${yellow}MarketDataTransmitter${reset}."
echo " ${yellow}MarketDataTransmitter${reset} could not be found."
else
# MarketDataTransmitter is present.
processes=$(ps -ef | grep -i "MarketDataTransmitter" | grep -v "grep" | grep -v "bash" | awk '{ print $8 }')
check_run=$(awk -v a="$processes" -v b="MarketDataTransmitter" 'BEGIN { print index(a, b) }')
if [ "$check_run" = "0" ]; then
# MarketDataTransmitter is not running.
if [ -e "srv.log" ]; then
if [ -s "srv.log" ]; then
if [ -d "logs" ]; then
date_time=$(date '+%Y%m%d_%H_%M_%S')
new_log_name="srv_$date_time.log"
mv srv.log $new_log_name
mv $new_log_name logs
else
mkdir logs
date_time=$(date '+%Y%m%d_%H_%M_%S')
new_log_name="srv_$date_time.log"
mv srv.log $new_log_name
mv $new_log_name logs
fi
else
echo "srv.log is empty and will be removed."
rm -rf srv.log
fi
else
# No srv.log but this is to start MarketDataTransmitter so we can ignore.
fi
./MarketDataTransmitter > srv.log &
echo "${yellow}MarketDataTransmitter${reset} has been started."
else
# MarketDataTransmitter is already running.
echo "${red}[ERROR]${reset} Could not start ${yellow}MarketDataTransmitter${reset}."
echo " ${yellow}MarketDataTransmitter${reset} is already running."
fi
fi
echo
However it is giving me syntax complaints saying:
syntax error near unexpected token `fi'
on the very last 'fi'
Does anyone know why?
Thanks.
[EDIT] Full code has been posted.
You have an else statement and fi statement with nothing between them on lines 44-46 (just a comment between them). In bash, you need to have some statement in the body of that else block, or take the else block out.
Related
my bash script wont run, and does not output anything past echo "Running gke old user cleanup". There is no fail message, it just doesn't run. Any suggestions?
#!/bin/bash
set -o pipefail
set -o nounset
date
echo "Running old user cleanup"
for user in $(awk -F':' '$1 ~ /^kub-[a-z0-9]{20}$/ { print $1 }' /etc/passwd); do
echo "Cleaning up '${user}'"
userdel -r "${user}"
rc=$?
if [[ $rc != 0 ]]; then
echo "Failed to cleanup '${user}': exit code: ${rc}"
else
echo "Successfully cleaned up '${user}'"
fi
done
Maybe simplify the loop.
while read user
do if userdel -r "${user}"
then echo "Successfully cleaned up '${user}'"
else echo "Failed to cleanup '${user}': exit code: '$?'"
fi
done < <( awk -F':' '$1 ~ /^gke-[a-z0-9]{20}$/ { print $1 }' /etc/passwd )
Should at least be easier to debug.
Add set -x as suggested to see what's being evaluated.
Although I was able to figure out my first script and get it to run, I am having issues with my second script. Basically I need to retrieve my deleted files and restore them in my created home directory. I was able to get some of question 2, and all of 3 and 4 to work successfully. The issue I have with question 2 is if I type up the file that I want to restore, it will pull up the file and inode number which is fine. However, if I run the script without the desired file, it will show a bunch of inodes and the command "Missing Operand". The missing operand command is one that I want since I created it in order to test that the files I want to restore exist. I have attached my code below. Again, I wonder what I got wrong. I did some of the suggestions shellcheck offered but I still got the same results.
Here is my code:
#!/bin/bash
#2.
fileName=$1
inode=$(ls -i $1 | cut -d " " -f1)
echo "safe_rm_restore $1_$inode"
#3.
function movingfile(){
if [ -e $HOME/deleted ] ;
then
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f3)
fi
}
movingfile $1
#4.
function safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
function restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f2) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?: word"
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
rm $(grep $1 $HOME/.restore.info | cut -d" " -f2)
mv $HOME/deleted $(grep $1/.restore.info | cut -d" " -f2)
fi
if [[ $word = "n" ]] ;
then
rm $1
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
function restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info | -d":" -f2)]];
then
$remove
fi
}
restored $1
I've followed the suggestions that you all gave me (and it moved me towards the right direction) but I still had some issues getting my operations to fully work. For instance, if no file name was given, my script was supposed to say Missing Operand but instead it gives all inode numbers in my file and my script freezes for sometime. Here is my updated second bash script. The indention looks great from my UNIX system but is somehow skewed when I transfer it on here. Thank you again!
#!/bin/bash
##2.
fileName="$1"
inode="$(ls -i $1 |cut -d" " -f1)"
echo "safe_rm_restore $1_$inode"
touch "$1"
##3.
movingfile(){
if [ -e $HOME/deleted ] ;
then
touch $1_$inode
mv $1_$inode $HOME/deleted $(grep $1 $HOME/.restore.info | cut -d" " -f4)
else
exit 1
fi
}
movingfile $1
##4.
safe(){
filename=$1
if [ ! -e $1 ] ;
then
echo "safe_rm_restore :cannot restore '$1': No such file or directory"
exit 1
elif [ $# -eq 0 ] ;
then
echo "safe_rm_restore: cannot restore '$1' : Missing operand"
exit 1
fi
}
safe $1
##5.
restoreFile(){
if [ -e $(grep $1 $HOME/.restore.info | cut -d" " -f4) ] ;
then
read -p "File currently exists. Do you want to overwrite y/n?:" word
if [[ $word = "yes" || $word = "Y" || $word = "y" ]] ;
then
mv $1_$inode $HOME/project $(grep $1/.restore.info | cut -d" " -f4)
fi
if [[ $word = "n" ]] ;
then
rm -r $1_$inode
exit 0
else
echo "Invalid Option"
exit 1
fi
fi
}
restoreFile $1
##6.
restored(){
remove=$(grep -v $1 $HOME/.restore.info | tee $HOME/.restore.info)
if [[ ! -e $HOME/deleted && -e $(grep $1 $HOME/.restore.info |cut -d":" -f4) ]];
then
$remove
fi
}
restored $1
This is my code:
echo
echo "WELCOME"
echo "-------------------------------------------------"
while true
do
echo
echo "Select A Menu Option"
echo "1: Ancestry History"
echo "2: Who is Online"
echo "3: What Process Any User is Running"
echo "4: Exit"
read mOption
case $mOption in
1) echo
echo "The Ancestry Tree For Current Process is....";
ps -ef > processes
grep "ps -ef" processes > grepProcesses
awk '{print $2, $3}' processes > awkProcesses
PID=$(awk '{print $2}' grepProcesses)
echo $PID
SPID=$(awk '{print $3}' grepProcesses)
PID=$SPID
end=0
while [ $end != 1 ]
do
echo " | "
echo $SPID
PID=$SPID
SPID=$(grep ^"$PID " awkProcesses | cut -d' ' -f2)
if [ "$PID" = "1" ]
then
end=1
fi
done
rm processes
rm grepProcesses
rm awkProcesses
;;
2) echo
echo "Users Currently Online";
who | cut -d' ' -f1
;;
3) echo
echo "Select a Currently Online User to View their Processes:"
index=0
who | while read onlineUser
do
echo "$index-$onlineUser" who|cut -d' ' -f1>>userList
index=$((index+1))
done
awk '{ print $0 }' userList
read choice
if [ $choice ]
then
echo
echo ***Process Currently Running***
person=$(grep ^$choice userList |cut -d'-' -f2)
ps -ef >> process
grep $person process
else
echo You have made a mistake. Please start over.
fi
rm userList
rm process
;;
4) echo
echo "Exiting..."
exit 1;;
*)
echo
echo "Invalid Input. Try Again."
;;
esac
done
Each time I run it I just keep getting the syntax error "hmwk1.sh: 17: hmwk1.sh: Syntax error: word unexpected (expecting "in")"
I looked up different syntax examples and it seems that my code looks correct. But my trial and error gets me nowhere to fixing my code.
Could I be missing a parenthesis or quotation marks of some kind?
If you simply press return on the prompt
read mOption
case $mOption in
then $mOption is an empty token, making the shell see just
case in
which is a syntax error. If you add
test -z "$mOption" && continue
in the middle, if will repair that problem.
i wrote alert log script and some how this is not working and not throwing any error when i execute the script
i am suspecting sed part is not working properly. could you please advice where i am doing wrong?
here is the piece of code
#!/bin/sh
## Heading #########################################################################################
#---------------------------------------------------------------------------------------#
# script usage #
#---------------------------------------------------------------------------------------#
_usage() {
echo "Usage: $0 ORACLE_SID "
} # _usage
ORACLE_SID="$1"
setenv ()
{
eval "$1=$2"
export "$1"
} # setenv
unsetenv ()
{
while [ $# -gt 0 ]
do
unset "$1"
shift
done
} # unsetenv
if [ $# -ne 1 ]; then
_usage
exit 1
fi
Env=/u01/app/oracle/config
HN=`uname -n`
ERROR_FILE=/tmp/${ORACLE_SID}_error.log
HN=`hostname`
DBA_MAIL="oracle.mail#company"
DBA_PAGE=""
#+--------------------------------------------------------------------------------------+
#| get oracle environment variables from our common env dir |
#+--------------------------------------------------------------------------------------+
if [ -r $Env/${ORACLE_SID}.env ]
then
. $Env/${ORACLE_SID}.env
else
ORACLE_SID=""
fi
#+--------------------------------------------------------------------------------------+
#| just checking for Oracle Env variables for connecting database |
#+--------------------------------------------------------------------------------------+
if [ "$ORACLE_SID" = "" ]
then
echo "ORACLE_SID is invalid"
exit 1
fi
if [ "$ORACLE_HOME" = "" ]
then
echo "The environment variable ORACLE_HOME must be set"
exit 1
fi
if [ "$ORACLE_BASE" = "" ]
then
echo "The environment variable ORACLE_BASE must be set"
exit 1
fi
_AlertLogLoc ()
{
ALERTLOG=`$ORACLE_HOME/bin/sqlplus -s "/as sysdba" << EOF
set head off pause off term on feed off timing off
select value from v\\$parameter where name like 'background_dump_dest';
exit;
EOF`
}
_AlertLogLoc
echo $ALERTLOG
export ALERTLOG
if [ -f $ALERTLOG/alert_${ORACLE_SID}.log ]; then
echo "Found Database Alert log"
else
echo "Alert log not found .. exit from script"
fi
if [ -f $ALERTLOG/alert_${ORACLE_SID}.skip ]; then
echo " ORACLE_SID skip error file found"
SKIP_ERR=`cat $ALERTLOG/alert_$ORACLE_SID.skip|xargs|sed -e 's/ /|/g'`
echo $SKIP_ERR
else
echo "No errors will be excluded"
fi
REC_CUR_ALSIZE=/oraworkspace/OSE/logs/alert_${ORACLE_SID}.size # file to record current alert log lines
#---------------------------------------------------------------------------------------------------------#
# let Capture ORA- error from the alert log #
#---------------------------------------------------------------------------------------------------------#
if [ -f $REC_CUR_ALSIZE ]; then
ALSIZE=`cat $REC_CUR_ALSIZE|sed -e 's/^[ \t]*//'`
ALSIZE=`expr $ALSIZE + 1`
else
ALSIZE=0
fi
if [ $ALSIZE -eq 0 ]; then
echo "PROBABLY RUNNUNG THE SCRIPT FIRST TIME"
sed -n $ALSIZE',$p' $ALERTLOG/alert_${ORACLE_SID}.log |egrep -v "$SKIP_ERR"|grep -i 'ORA-' > /tmp/${ORACLE_SID}_error.log
#`wc -l $ALERTLOG/alert_${ORACLE_SID}.log > $REC_CUR_ALSIZE
cat $ALERTLOG/alert_${ORACLE_SID}.log|wc -l > /oraworkspace/OSE/logs/alert_${ORACLE_SID}.size
#ALSIZE=`cat $ALERTLOG/alert_${ORACLE_SID}.log |wc -l`
else
sed -n ${ALSIZE}',$p' $ALERTLOG/alert_${ORACLE_SID}.log |egrep -v "$SKIP_ERR"|grep -i 'ORA-' > /tmp/${ORACLE_SID}_error.log
#wc -l $ALERTLOG/alert_${ORACLE_SID}.log >> $REC_CUR_ALSIZE
cat $ALERTLOG/alert_${ORACLE_SID}.log |wc -l > /oraworkspace/OSE/logs/alert_${ORACLE_SID}.size
fi
#---------------------------------------------------------------------------------------------------------#
# Notify if any errors are found #
#---------------------------------------------------------------------------------------------------------#
ERR_CNT=`cat /tmp/${ORACLE_SID}_error.log |wc -l`
if [ $ERR_CNT -ne 0 ]; then
echo "Errors found in the alert log. send email notification"
mailx -s "${HN}:${ORACLE_SID} ORA error Found in the alert log" ${DBA_MAIL} < $ERROR_FILE
#mailx -s "${HN}:${ORACLE_SID} ORA error Found in the alert log" ${DBA_MAIL} < $ERROR_FILE
else
echo " No errors found in the alert log"
fi
If $ALERTLOG/alert_$ORACLE_SID.skip doesn't exist or is empty (around line 94), the egrep -v "$SKIP_ERR" will exclude all lines from the sed output, so it will not have a chance to see any remaining ORA- errors.
ALSIZE=1
SKIP_ERR=""
sed -n $ALSIZE',$p' $ALERTLOG/alert_${ORACLE_SID}.log |\
egrep -v "$SKIP_ERR"|wc -l
0
SKIP_ERR="dummy"
sed -n $ALSIZE',$p' $ALERTLOG/alert_${ORACLE_SID}.log |\
egrep -v "$SKIP_ERR"|wc -l
15165
So you need to set your SKIP_ERR to something when it's not set or empty (if your skip file is empty). You haven't said if that is the case or shown the script output, but it seems to work apart from that.
Also not that if ALSIZE is zero sed isn't happy, at least in RHEL 5:
ALSIZE=0
SKIP_ERR="dummy"
sed -n $ALSIZE',$p' $ALERTLOG/alert_${ORACLE_SID}.log |\
egrep -v "$SKIP_ERR"|wc -l
sed: -e expression #1, char 4: invalid usage of line address 0
0
And when you test that the file exists at line 91, you show a message stating that and suggesting you'll stop there, but there is no exit after line 94; doesn't seem to be relevant here but seems like an oversight?
enter image description hereI was trying to see how a shell scripts work and how to run them, so I toke some sample code from a book I picked up from the library called "Wicked Cool Shell Scripts"
I re wrote the code verbatim, but I'm getting an error from Linux, which I compiled the code on saying:
'd.sh: line 3: syntax error near unexpected token `{
'd.sh: line 3:`gmk() {
Before this I had the curly bracket on the newline but I was still getting :
'd.sh: line 3: syntax error near unexpected token
'd.sh: line 3:`gmk()
#!/bin/sh
#format directory- outputs a formatted directory listing
gmk()
{
#Give input in Kb, output converted to Kb, Mb, or Gb for best output format
if [$1 -ge 1000000]; then
echo "$(scriptbc -p 2 $1/1000000)Gb"
elif [$1 - ge 1000]; then
echo "$$(scriptbc -p 2 $1/1000)Mb"
else
echo "${1}Kb"
fi
}
if [$# -gt 1] ; then
echo "Usage: $0 [dirname]" >&2; exit 1
elif [$# -eq 1] ; then
cd "$#"
fi
for file in *
do
if [-d "$file"] ; then
size = $(ls "$file"|wc -l|sed 's/[^[:digit:]]//g')
elif [$size -eq 1] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size ="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(gmk $size))|"
fi
done | \
sed 's/ /^^^/g' |\
xargs -n 2 |\
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%39s %-39s\n", $1, $2}'
exit 0
if [$#-gt 1]; then
echo "Usage :$0 [dirname]" >&2; exit 1
elif [$# -eq 1]; then
cd "$#"
fi
for file in *
do
if [ -d "$file" ] ; then
size =$(ls "$file" | wc -l | sed 's/[^[:digit:]]//g')
if [ $size -eq 1 ] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size ="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(convert $size))|"
fi
done | \
sed 's/ /^^^/g' | \
xargs -n 2 | \
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%-39s %-39s\n", $1, $2 }'
exit 0
sh is very sensitive to spaces. In particular assignment (no spaces around =) and testing (must have spaces inside the [ ]).
This version runs, although fails on my machine due to the lack of scriptbc.
You put an elsif in a spot where it was supposed to be if.
Be careful of column alignment between starts and ends. If you mismatch them it will easily lead you astray in thinking about how this works.
Also, adding a set -x near the top of a script is a very good way of debugging what it is doing - it will cause the interpreter to output each line it is about to run before it does.
#!/bin/sh
#format directory- outputs a formatted directory listing
gmk()
{
#Give input in Kb, output converted to Kb, Mb, or Gb for best output format
if [ $1 -ge 1000000 ]; then
echo "$(scriptbc -p 2 $1/1000000)Gb"
elif [ $1 -ge 1000 ]; then
echo "$(scriptbc -p 2 $1/1000)Mb"
else
echo "${1}Kb"
fi
}
if [ $# -gt 1 ] ; then
echo "Usage: $0 [dirname]" >&2; exit 1
elif [ $# -eq 1 ] ; then
cd "$#"
fi
for file in *
do
if [ -d "$file" ] ; then
size=$(ls "$file"|wc -l|sed 's/[^[:digit:]]//g')
if [ $size -eq 1 ] ; then
echo "$file ($size entry)|"
else
echo "$file ($size entries)|"
fi
else
size="$(ls -sk "$file" | awk '{print $1}')"
echo "$file ($(gmk $size))|"
fi
done | \
sed 's/ /^^^/g' |\
xargs -n 2 |\
sed 's/\^\^\^/ /g' | \
awk -F\| '{ printf "%39s %-39s\n", $1, $2}'
exit 0
By the way, with respect to the book telling you to modify your PATH variable, that's really a bad idea, depending on what exactly it advised you to do. Just to be clear, never add your current directory to the PATH variable unless you intend on making that directory a permanent location for all of your scripts etc. If you are making this a permanent location for your scripts, make sure you add the location to the END of your PATH variable, not the beginning, otherwise you are creating a major security problem.
Linux and Unix do not add your current location, commonly called your PWD, or present working directory, to the path because someone could create a script called 'ls', for example, which could run something malicious instead of the actual 'ls' command. The proper way to execute something in your PWD, is to prepend it with './' (e.g. ./my_new_script.sh). This basically indicates that you really do want to run something from your PWD. Think of it as telling the shell "right here". The '.' actually represents your current directory, in other words "here".