**UPDATE Issues with .SH file running Correctly - shell

I am trying to use this script to be able to shut down my ESXi server based on network connectivity. I found this script online, on the vmcommunity and no one seems to be having the same issues that I am. When I run this script It returns syntax error: unexpected word (expecting "in"). However the in is there
allInterfaces=$(esxcfg-nics -l | grep vmnic | awk '{print $1}' | awk '$1=$1' OFS=" " RS=)
while [ $# -gt 0 ];
do
case "$1" in
-v) verbose=1;;
-t) downCycles=$2; shift;;
-i) shift; break;;
--) shift; break;;
-*) errorLog "wrong parameter:" "$#" ;;
*) break;;
esac
done
shift
Any advice would be extremely helpful. Below if the full script that I am trying to use.
#!/bin/bash
verbose=0
downCycles=3
stateCounter="/tmp/auto-shutdown.counter"
log() {
logger "auto-shutdown: $1"
if [ $verbose -gt 0 ]; then
echo "$1"
fi
}
errorLog() {
logger "auto-shutdown error: $1"
echo -e >&2 "\n$1\n"
echo -e >&2 "auto-shutdown.sh: shutdown vmware ESXi if network interfaces are down for a number of cycles"
echo -e >&2 "-------------------------------------------------------------------------------------------------"
echo -e >&2 "usage: $0 [-v] [-t cycles] [-i vmnic# vmnic# ...]\n"
echo -e >&2 " -v: verbose\n"
echo -e >&2 " vmnic#: selected vmnic interfaces to monitor"
echo -e >&2 " defaults to all available interfaces\n"
echo -e >&2 " cycles: the down condition is reached, if all selected vmnic interfaces"
echo -e >&2 " have been down for <cycles> consecutive executions of this script\n"
echo -e >&2 "(c) 2011-10-22 by Ralf Lueders, support#lrconsult.com"
echo -e >&2 "-------------------------------------------------------------------------------------------------\n"
exit 1
}
if [ ! -e $stateCounter ]; then
echo 0 > $stateCounter
fi
allInterfaces=$(esxcfg-nics -l | grep vmnic | awk '{print $1}' | awk '$1=$1' OFS=" " RS=)
while [ $# -gt 0 ];
do
case "$1" in
-v) verbose=1;;
-t) downCycles=$2; shift;;
-i) shift; break;;
--) shift; break;;
-*) errorLog "wrong parameter:" "$#" ;;
*) break;;
esac
done
shift
selectedInterfaces=$*
nosi=0
for interface in $selectedInterfaces; do
if [ "$(expr "$allInterfaces" : ".*$interface.*")" -eq 0 ]; then
errorLog "$0 error: interface $interface does not exist"
fi
nosi=$( $nosi + 1 )
done
if [ ${#selectedInterfaces} -eq 0 ]; then
selectedInterfaces=$allInterfaces
fi
if [ $verbose -gt 0 ]; then
echo "monitoring interface(s) $selectedInterfaces ..."
fi
downState=1
for interface in $selectedInterfaces; do
state=$(esxcfg-nics -l | grep "$interface" | awk '{print tolower($4)}')
if [ "$state" = "up" ]; then
downState=0
fi
done
count=$(cat $stateCounter)
if [ "$count" -eq "$downCycles" ]; then
log "initiating system shutdown..."
echo 0 > $stateCounter
/sbin/shutdown.sh
/sbin/poweroff
else
if [ $downState -eq 1 ]; then
count=$( $count + 1 )
countDown=$( "$downCycles - $count" )
log "the interface(s) $selectedInterfaces have now been down for $count cycles, $countDown cycles left before system shutdown."
else
count=0
fi
fi
echo $count > $stateCounter
I have used Charles' suggestions and I am no longer getting errors in ShellCheck. However I am still getting the same error I encountered before where it say that I am missing an in that is clearly there. Anyone see anything else that could be edited to solve this issue. I am really not familiar with shell scripting at all, so any information would be helpful.

Related

How to make it manditory for options to be spaced for bash scripts

I have the following script.
I would like to modify it so that if I were to call temp.sh with both the options, I would have to space them. Ie: A call to the script like temp.sh -fc30 should be invalid, rather it should be temp.sh -f -c 30
ARGS=$(getopt -o c:f -l "charlie:fox" -n "temp.sh" -- "$#");
#bad args
if [ $? -ne 0 ];
then
exit 1
fi
eval set --"$ARGS";
while true; do
case "$1" in
-c|--charlie)
shift;
if [ -n "$1" ]; then
echo "-c =: $1";
shift;
fi
;;
-f|--fox)
shift;
echo "fox used";
;;
--)
shift;
break;
;;
esac
done
Just don't use getopt.
#!/bin/bash
# parse options
while [[ $# -gt 0 ]]; do
case $1 in
-c|--charlie)
echo "$1 = $2"
shift
;;
-f|--fox)
echo "fox used"
;;
--)
shift
break
esac
shift
done
# do script

"`$#': not a valid identifier" error in bash script

I am working on a shell script that will allow for the user to input a file name(s) into the command prompt, and the script will locate the executable file and determine if they could have been executed. However, when I attempt to run it, I get a "line 45 `$#': not a valid identifier" error message.
This is my first script and can't figure out how to address this error. I am hopeful that the rest of the script is ok, but I haven't been able to get past this one error to test it out.
Any help is greatly appreciated!
#!/bin/bash
FINDALL=FALSE
while :
do
case $1 in
-a) FINDALL=TRUE
shift ;;
-h) echo “Usage $0 [-a] commands…”
exit 0 ;;
*) break ;;
esac
done
for $# in $file
do
case $file in
*/*) if [ -x “$file” ]
then
echo $file
elif [ -d “$file” ]
then
echo $file is NOT found
fi
shift ;;
*) FOUND=FALSE ;;
esac
done
case $PATH in
:*) PATH=”.:$PATH” ;;
*::*) PATH=`echo $PATH | sed -e ‘s/::/:.:/g’` ;;
*:) PATH=”$PATH:.” ;;
esac
command=”$1”
IFS=$OLDIFS
IFS=:
set -- $PATH
IFS=$OLDIFS
case $command in
*/*) echo $command ;;
*) FOUND=FALSE
for P
do
if [ ! -d “$P/$command” -a -x “$P/$command” ]
then
FOUND=TRUE
echo $command
break
fi
done
if [ “$FOUND” = FALSE ]
then
echo “Command $command not found in your search path”
fi ;;
esac

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

Bash script and getopts outputting saved variables

I'm trying to put together a script to monitor files and im having a hard tiem with getopts. If I run more than once the shell values dont changes... There's a ton of clean up but I've been stuck on this one issue for a couple hours so ...
#!/bin/bash
function printUsage {
echo "Usage: $0 [-e environment] [-r region] [-l logtype]"
echo "Requirements:"
echo " -e environment to look in; prod or dev"
echo " -r 3 digit region designation"
echo " -l log type to find; soap, message, main, service, or detail"
echo " example: $0 -e dev -r 111 -f soap"
exit 0
}
if [ $# -lt 1 ]; then
printUsage
fi
while getopts "e:r:l:" opt; do
case $opt in
e)
environment="$OPTARG"
;;
r)
region="$OPTARG"
;;
l)
logtype="$OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
printUsage;;
:)
echo "-$OPTARG requires an argument"
printUsage;;
esac
done
#build array of directories to search based on argument
function buildProductionArray {
# assume these are here
logpaths=( )
}
#build array of directories to search based on argument
function buildDevArray {
# assume these are here
logpaths=( )
}
function validateArguments {
#validate the environment
if [ "$(echo "$environment" | tr "[:lower:]" "[:upper:]")" == "PROD" ]; then
buildProductionArray
elif [ "$(echo "$environment" | tr "[:lower:]" "[:upper:]")" == "DEV" ]; then
buildDevArray
else
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid environment" >&2; exit 1
fi
#validate the region
if ! [ "$region" -eq "$region" ] 2>/dev/null; then
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid region" >&2; exit 1
fi
#validate the logtype
function in_array() {
elements=${1}
element=${2}
for i in "${elements[#]}" ; do
if [ "$i" == "$element" ] ; then
return 1
fi
done
return 0
}
logvalues=(soap message service main detail)
log="$(echo "$logtype" | tr '[:upper:]' '[:lower:]')"
echo "$log"
if in_array logvalues "${log}"; then
if [[ "$log" == "service" || "$log" == "detail" ]]; then
log="-$log-time-"
else
log="-$log-"
fi
else
echo "Usage: findlog [-e environment] [-r region] [-l logtype]"
echo "Invalid environment" >&2; exit 1
fi
}
validateArguments
for i in "${logpaths[#]}"
do
#assume this is here
done

need a shell script to convert big endian to little endian

I need a shell script program to print the hexadecimal number from big endian to little endian
For example
Input: my virtual address = 00d66d7e
Output: 7e6dd600
How can I can I create this in a bash script?
Just had to do this... but from decimal to little endian.. adapting that here:
echo 00d66d7e | tac -rs .. | echo "$(tr -d '\n')"
achieves the desired result, for arbitrarily sized hexadecimal representations of unsigned integers.
(h/t 'tac -rs' MestreLion, very nice!)
For 32 bit addresses, assuming it's zero padded:
v=00d66d7e
echo ${v:6:2}${v:4:2}${v:2:2}${v:0:2}
# 7e6dd600
Based on Karoly's answer you could use the following script, reading an argument or piped input:
#!/bin/bash
# check 1st arg or stdin
if [ $# -ne 1 ]; then
if [ -t 0 ]; then
exit
else
v=`cat /dev/stdin`
fi
else
v=$1
fi
i=${#v}
while [ $i -gt 0 ]
do
i=$[$i-2]
echo -n ${v:$i:2}
done
echo
For e.g. you could save this script as endian.sh and make it executable with:
chmod u+x endian.sh
Then:
echo 00d66d7e | ./endian.sh
gives you:
7e6dd600
For a different length string:
echo d76f411475428afc90947ee320 | ./endian.sh
result would be:
20e37e9490fc8a427514416fd7
#Update: Modified the script to accept the input either as an argument or from stdin, addressing Freewind's request. So now:
./endian.sh d76f411475428afc90947ee320
also works and gives you:
20e37e9490fc8a427514416fd7
This works for dash (and many other shells) :
v=0x12345678
v2=$(( (v<<8 & 0xff00ff00) | (v>>8 & 0xff00ff) ))
v2=$(( (v2<<16 & 0xffff0000) | v2>>16 ))
printf '0x%08x\n' $v2
Result should be "0x78563412"
${v:6:2} is for bash.
In response to Freewind's comment request and building off of hutheano's great answer, I wrote my own bash script and I include a condensed version below. The full script can be downloaded here.
The following implementation accounts for odd length strings, 0x or \x prefixes, and multiple output formats and can be used like the following:
$ be2le d76f411475428afc90947ee320 0xaaff 0xffa '\x3'
20e37e9490fc8a427514416fd7
0xffaa
0xfa0f
\x03
be2le bash script
#!/bin/bash
args=()
format=preserve
delimiter="\n"
nonewline=false
join=false
strip=false
while (( "$#" )); do
case "$1" in
-h|--help) usage;;
-f) format=$2; shift 2;;
--format=*) format="${1#*=}"; shift;;
-d) delimiter=$2; shift 2;;
--delimiter=*) delimiter="${1#*=}"; shift;;
-n|--no-newline) nonewline=true; shift;;
-j|--join) join=true; shift;;
-s|--strip-null) strip=true; shift;;
-*|--*) echo "Error: unsupported flag $1 specified"; exit 1;;
*) args=( "${args[#]}" "$1" ); shift;;
esac
done
case "$format" in
preserve);;
int) prefix="0x";;
char) prefix="\x";;
raw) ;;
*) echo "Error: unsupported format $format"; exit 1;;
esac
n=0
parts=()
for arg in ${args[#]}; do
digest=""
prefix=""
# remove prefix if string begins with "0x"
if [[ $arg =~ ^[0\\]x ]]; then
if [ "$format" == "preserve" ]; then
prefix=${arg:0:2}
fi
arg=${arg:2}
fi
# zero-pad if string has odd length
if [ $[${#arg} % 2] != 0 ]; then
arg="0$arg"
fi
part=""
i=${#arg}
while [ $i -gt 0 ]; do
i=$[$i-2]
byte=${arg:$i:2}
if [ $strip == true ] && [ -z "$part" ] && [ $byte == "00" ]; then
continue
fi
case "$format" in
int) part="$part"'0x'"$byte ";;
char) part="$part\x$byte";;
raw) part="$part$(printf "%b" "\x$byte")";;
*) part="$part$byte";;
esac
done
digest="$prefix$digest$part"
parts=( "${parts[#]}" "$digest" )
n=$[$n+1]
done
if [ $join == true ]; then
case "$format" in
*) printf "%s" "${parts[#]}";;
esac
else
i=0
for part in "${parts[#]}"; do
if [[ $(($i + 1)) < $n ]]; then
printf "%s$delimiter" "$part"
else
printf "%s" "$part"
fi
i=$(($i+1))
done
fi
if [ $nonewline == false ]; then
echo
fi
This script is for flipping 16 bit data.
#!/bin/bash
if [ -t 0 ]; then exit; fi
data=`cat /dev/stdin | od -An -vtx1 | tr -d ' ' | tr -d '\n'`
length=${#data}
i=0
while [ $i -lt $length ]; do
echo -n -e "\x${data:$[$i+2]:2}"
echo -n -e "\x${data:$[$i]:2}"
i=$[$i+4]
done

Resources