First, let me preface this post by saying that I wouldn't consider myself an expert shell script programmer. I first learned the C-Shell programming language during the early 1990s while in undergraduate school; I learned Bash programming later on as well. Over the decades, I have written many shell scripts for work & personal use, mainly to simplify common CLI terminal sessions, and to automate some regular routine tasks that happen often during my S/W development work. However, I don't write shell scripts frequently enough to consider myself an expert, so the following questions, suggestions & recommendations are made in the spirit of sharing some "nuggets of wisdom" that I've learned along the way; they are certainly not meant as destructive criticism of the work you've done, nor are they meant to diminish what you have accomplished with the script you have shared on this thread.
Usage of the "
continue" command??
Bash:
# Set Script Mode
if [ -z "$(echo ${1#})" ] >/dev/null;then
...
...
else
mode="${1#}"
continue
fi
Bash:
if [[ ! -f "$CONFIGFILE" ]] >/dev/null;then
echo -e "${RED}${0##*/} - No Configuration File Detected - Run Install Mode${NOCOLOR}"
else
continue
exit
fi
As shown above, I noticed that fairly often in your script you use the "
continue" command within
if-else statements, and I'm wondering what your reasons are for using it that way. AFAIK, the only purpose of the "
continue" command is to skip the current iteration when executing *
within* a loop (e.g.
for,
while, and
until loops), and I've never seen it used within simple
if-else statements so its inclusion seems superfluous & completely unnecessary to me. However, it's possible that I may be unaware of some other syntax forms where the "
continue" command serves a purpose. Could you elaborate on what your reasons are (for my own edification)?
In your script, you have created a custom function named "
kill"
Bash:
# Kill Script
kill ()
{
echo -e "${RED}Killing ${0##*/}...${NOCOLOR}"
echo "$(date "+%D @ %T"): $0 - Kill: Killing ${0##*/}..." >> $LOGPATH
sleep 3 && killall ${0##*/}
exit
}
It's generally considered bad coding practice to give a custom shell function exactly the same name as a native, built-in command already found in the underlying OS *
unless* you are intentionally replacing the built-in command with your own version that improves upon or enhances the existing native command.
At one point in the code you have a statement where the script calls itself to create a cron job:
Bash:
# Create Initial Cron Jobs
sh "$0" cron
It's generally considered bad coding practice for a shell script to call itself (and generate another process) *
unless* it's for performing some recursive operations that require a controlled repetitive execution of all or part of the script. It's much simpler to call the existing internal function from within the current execution instance of the script.
Bash:
# Create Initial Cron Jobs
cronjob
In the current "
cronjob()" function you have an unnecessary
'else' statement:
Bash:
# Cronjob
cronjob ()
{
if [ -z "$(crontab -l | grep -e "$0")" ] >/dev/null; then
...
...
else
exit
fi
exit
}
Here's the modified version:
Bash:
# Cronjob
cronjob ()
{
if [ -z "$(crontab -l | grep -e "$0")" ] >/dev/null; then
...
...
fi
exit
}
Here is a modified version of the "
logclean()" function which not only avoids creating a temporary file but also avoids doing all that work when the logfile has fewer lines than indicated by the
LOGNUMBER variable:
Bash:
logclean ()
{
if [ "$mode" != "logclean" ] || [ ! -f "$LOGPATH" ] ; then exit 1 ; fi
local NumOfLogLines="$(wc -l "$LOGPATH" | awk '{print $1}')"
if [ $NumOfLogLines -gt $LOGNUMBER ]
then
echo "${0##*/} - Deleting logs older than last $LOGNUMBER messages..."
echo "$(date "+%D @ %T"): $0 - Log Cleanup: Deleting logs older than last $LOGNUMBER messages..." >> $LOGPATH
sed -i 1,$((++NumOfLogLines - LOGNUMBER))d "$LOGPATH"
sleep 1
fi
exit 0
}
There are other code sections in the script that would probably benefit from further review and then applying more refactoring techniques, but some parts are not easy to follow because of the formatting style. Also, I think I might be getting on a topic that's beyond the scope of this thread, and perhaps even beyond the scope/purpose of this forum (if I'm not mistaken).
I would like, however, to give one last suggestion. I highly recommend that you reformat the script to include appropriate indentation not only to make it much more readable but also to visually provide clues to the reader as to the structure and logic flows in the script. This is not merely an aesthetic concern. When source code is formatted with proper indentation, it helps to follow much more easily & readily the different possible paths of execution and makes it easier to debug, change, remove, or add lines of code as needed while at the same time minimizing the risk of introducing new bugs. All this is conducive to better software quality. It's especially important when the code has statements placed at multiple nesting levels. The "
wanstatus()" function is an example where if reformatted with proper indentation it would certainly make it much easier to follow the logic flows & execution paths found at the different nesting levels.
My 2 cents.