command not executing when called from a case statement in bash - bash

I'm stuck and trying to troubleshoot why the command within the case statement will not execute within this bash script.
If I copy and paste the command into the command line and hardcode the value it will work.
Example:
psql -h mycluster-1.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="foo_bar" -f getTableDetails.sql
In the script, I encased the command within parentheses for possible whitespace issues:
#!/usr/local/bin/bash
set -e
set -x
cluster_to_endpoint() {
case "$1" in
c01)
RUNCMD=$(psql -h mycluster-1.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql)
;;
c02)
RUNCMD=$(psql -h mycluster-2.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql)
;;
esac
}
while getopts ":c:n:" opt; do
case $opt in
c) cluster="$OPTARG";;
n) name="$OPTARG";;
*) usage
exit 1
;;
esac
done
I am executing the script like so: ./myscript.sh -c c01 -n foo_bar
I've also tried just removing the () as well:
c01)
psql -h mycluster-2.us-east-1.redshift.amazonaws.com -U masteruser -d dev -p 5439 -v v1="$NAME" -f getTableDetails.sql;;
It looks like the variables are set.
$ ./myscript.sh -c c01 -n foo_bar
+ getopts :c:n: opt
+ case $opt in
+ cluster=c01
+ getopts :c:n: opt
+ case $opt in
+ name=foo_bar
+ getopts :c:n: opt
So why isn't the command executing? Thanks.

The command that isn't executing is inside a function, cluster_to_endpoint, that's never called.

Related

How to append the variable to linux command and then execute the final linux command($cmd: qic-run -t /mnt/etc/ -d 1000) using ksh

teststr="-t /mnt/etc/ -d 1000"
echo $teststr
cmd="qic-run $teststr"
echo $cmd
qic-run -t /mnt/etc/ -d 1000
For a single/simple command:
args=(-t /mnt/etc/ -d 1000)
qic-run "${args[#]}"

How to make runuser correctly forward all command line arguments, instead of trying to interpret them?

I got this simple script:
#!/bin/bash
SOURCE_USER=$USER
DESTINE_USER=$1
id -u $SOURCE_USER > /dev/null 2>&1
if [ "$?" == "1" ] || [ -z $SOURCE_USER ]
then
printf "Error: Invalid source user '$SOURCE_USER'\\n"
exit 1
fi
if [ -z $DESTINE_USER ]
then
printf "Error: Invalid destine user '$DESTINE_USER'\\n"
exit 1
fi
SOURCE_GROUPS=$(id -Gn ${SOURCE_USER} | sed "s/${SOURCE_USER} //g" | sed "s/ ${SOURCE_USER}//g" | sed "s/ /,/g")
SOURCE_SHELL=$(awk -F : -v name=${SOURCE_USER} '(name == $1) { print $7 }' /etc/passwd)
id -u $DESTINE_USER > /dev/null 2>&1
if [ "$?" == "1" ]
then
printf "Creating destine user %s\\n" "$DESTINE_USER"
useradd --groups ${SOURCE_GROUPS} --shell ${SOURCE_SHELL} --create-home ${DESTINE_USER}
passwd ${DESTINE_USER}
xhost '+si:localuser:$DESTINE_USER'
sudo usermod -G "$SOURCE_USER" "$DESTINE_USER"
else
printf "Updating destine user '%s' with groups '%s' and shell '%s'\\n" "$DESTINE_USER" "$SOURCE_GROUPS" "$SOURCE_SHELL"
sudo usermod -a -G "$SOURCE_GROUPS" "$DESTINE_USER"
sudo chsh -s "$SOURCE_SHELL" "$SOURCE_USER"
fi
sudo runuser sublime_vanilla -c "${#:2}"
I run it like this:
$ bash run_as_user.sh sublime_vanilla /usr/bin/subl -n "./New Empty File"
But when I run it, I got this error:
runuser: invalid option -- 'n'
Try 'runuser --help' for more information.
But if I replace sudo runuser sublime_vanilla -c "${#:2}" with sudo runuser sublime_vanilla -c "\"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\" \"${#:9}\""
Then, Sublime Text correctly opens the file "./New Empty File" in a new window.
How to make runuser correctly understand all argument with a variable number of command line arguments, i.e., without hard coding "\"$2\" \"$3\" \"$4\" ..."?
This is slightly different from your last question because you have to make the expansion of the arguments into a single string for the -c option.
The bash printf formatter %q is your friend here:
cmd=$( printf '%q ' "${#:2}" )
sudo runuser sublime_vanilla -c "$cmd"
On the other hand, a quick perusal through the runuser man page suggests:
sudo runuser -u sublime_vanilla "${#:2}"
Another thought: sudo runuser -u sublime_vanilla -- "${#:2}" with the double hyphens to indicate the end of the runuser options.

Build a bash command with conditional parameters and cuote parameters

I need to build a bash command in a script depending on some cuote or normal parameters. For example:
BAYES)
class="weka.classifiers.bayes.BayesNet"
A="-D -Q weka.classifiers.bayes.net.search.local.K2 -- -P 1 -S BAYES -E"
B="weka.classifiers.bayes.net.estimate.SimpleEstimator -- -A 0.5" ;;
LOGISTIC)
class="weka.classifiers.functions.Logistic"
A="-R 1.0E-8 -M -1 -num-decimal-places 4" ;;
SIMPLELOG)
class="weka.classifiers.functions.SimpleLogistic"
A="-I 0 -M 500 -H 50 -W 0.0" ;;
SMO)
class="weka.classifiers.functions.SMO"
A="-C 1.0 -L 0.001 -P 1.0E-12 -N 0 -V -1 -W 1 -K"
A1="weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0" ;;
IBK)
class="weka.classifiers.lazy.IBk"
A="-K 1 -W 0 -A "
A1="weka.core.neighboursearch.LinearNNSearch -A"
A2="weka.core.EuclideanDistance -R first-last" ;;
KSTAR)
class="weka.classifiers.lazy.KStar"
A="-B 20 -M a" ;;
...
java -Xmx"$mem"m -cp "$WEKA_INSTALL_DIR/weka.jar" $class -s $i -t "$file" $A "$A1" $B "$B1"
However, my problem is that in some conditions, when $A1 is empty, the "$A1" parameter is not valid. The same with "$B1". And the parameter could be in any combination ($A1 with $B1, $A1 without $B2, ...).
Also I've tried include $A1 in $A as following:
A="-C 1.0 -L 0.001 -P 1.0E-12 -N 0 -V -1 -W 1 -K \"weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0\""
and execute:
java -Xmx"$mem"m -cp "$WEKA_INSTALL_DIR/weka.jar" $class -s $i -t "$file" $A
but this doesn't work.
You cannot safely and reliably store multiple arguments in a single string; you need to use arrays; this is their intended use case. Make sure to initialize any arrays that won't be used, so that they "disappear" when expanded.
# If A is undefined, "${A[#]}" is an empty string.
# But if A=(), then "${A[#]}" simply disappears from the command line.
A=()
B=()
A1=()
A2=()
case $something in
BAYES)
class="weka.classifiers.bayes.BayesNet"
A=(-D -Q weka.classifiers.bayes.net.search.local.K2 -- -P 1 -S BAYES -E)
B=(weka.classifiers.bayes.net.estimate.SimpleEstimator -- -A 0.5);;
LOGISTIC)
class="weka.classifiers.functions.Logistic"
A=(-R 1.0E-8 -M -1 -num-decimal-places 4);;
SIMPLELOG)
class="weka.classifiers.functions.SimpleLogistic"
A=(-I 0 -M 500 -H 50 -W 0.0) ;;
SMO)
class="weka.classifiers.functions.SMO"
A=(-C 1.0 -L 0.001 -P 1.0E-12 -N 0 -V -1 -W 1 -K)
A1=(weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0) ;;
IBK)
class="weka.classifiers.lazy.IBk"
A=(-K 1 -W 0 -A)
A1=(weka.core.neighboursearch.LinearNNSearch -A)
A2=(weka.core.EuclideanDistance -R first-last);;
KSTAR)
class="weka.classifiers.lazy.KStar"
A=(-B 20 -M a) ;;
esac
and always quote parameter expansions.
java -Xmx"$mem"m -cp "$WEKA_INSTALL_DIR/weka.jar" \
"$class" -s "$i" -t "$file" "${A[#]}" "${A1[#]}" "${B[#]}" "${B1[#]}"
SOLUTION:
I solved all my problems using only a parameter A like this:
BAYES)
class="weka.classifiers.bayes.BayesNet"
A=(-D -Q weka.classifiers.bayes.net.search.local.K2 -- -P 1 -S BAYES -E weka.classifiers.bayes.net.estimate.SimpleEstimator -- -A 0.5);;
SMO)
class="weka.classifiers.functions.SMO"
A=(-C 1.0 -L 0.001 -P 1.0E-12 -N 0 -V -1 -W 1 -K "weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0");;
java -Xmx"$mem"m -cp "$WEKA_INSTALL_DIR/weka.jar" $class -s $i -t "$file" "${A[#]}"
From your question, I did:
Initialized the variables
Completed the case statement
Removed some not required double quotes
Defined some variables for which you did not provide values for
backslash your double quotes if you must have then in the java command
If you need double quotes for certain variables, put these in the variables. This way you will not have "" in your java command if the variables is empty. I did this for A1 in case IBK.
This will get you started, modify as required:
#!/bin/bash
#
mem="512"
WEKA_INSTALL_DIR='/opt/weka'
class=""
i="value-of-i"
A=""
A1=""
B=""
B1=""
file="SOMEFILE"
case $1 in
'BAYES')
class="weka.classifiers.bayes.BayesNet"
A="-D -Q weka.classifiers.bayes.net.search.local.K2 -- -P 1 -S BAYES -E"
B="weka.classifiers.bayes.net.estimate.SimpleEstimator -- -A 0.5"
;;
'LOGISTIC')
class="weka.classifiers.functions.Logistic"
A="-R 1.0E-8 -M -1 -num-decimal-places 4"
;;
'SIMPLELOG')
class="weka.classifiers.functions.SimpleLogistic"
A="-I 0 -M 500 -H 50 -W 0.0"
;;
'SMO')
class="weka.classifiers.functions.SMO"
A="-C 1.0 -L 0.001 -P 1.0E-12 -N 0 -V -1 -W 1 -K"
A1="weka.classifiers.functions.supportVector.PolyKernel -C 250007 -E 1.0"
;;
'IBK')
class="weka.classifiers.lazy.IBk"
A="-K 1 -W 0 -A "
A1="\"weka.core.neighboursearch.LinearNNSearch -A\""
A2="weka.core.EuclideanDistance -R first-last"
;;
'KSTAR')
class="weka.classifiers.lazy.KStar"
A="-B 20 -M a"
;;
*)
# default options
;;
esac
echo java -Xmx${mem}m -cp $WEKA_INSTALL_DIR/weka.jar $class -s $i -t $file $A $A1 $B $B1
Example:
./test.bash LOGISTIC
java -Xmx512m -cp /opt/weka/weka.jar weka.classifiers.functions.Logistic -s value-of-i -t SOMEFILE -R 1.0E-8 -M -1 -num-decimal-places 4
./test.bash IBK
java -Xmx512m -cp /opt/weka/weka.jar weka.classifiers.lazy.IBk -s value-of-i -t SOMEFILE -K 1 -W 0 -A "weka.core.neighboursearch.LinearNNSearch -A"

How to substitute variables correctly within a function

I'm having difficulty getting the correct variable substitution to work within this function, especially the use of echo "$(...) string.
outputOFF ()
{
host='mydevreporting.com'
_pw='123456foobar'
_dt=$(date +'%m-%d-%y')
exp="SELECT * FROM metrics.account_use where account='foo' and profile='bar' order by date desc;";
echo "$(grep real < <({ time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"} 2>&1)):localhost:${_dt}"
#echo "$(grep real < <(\{ time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"\} 2>&1)):localhost:${_dt}"
}
From the command line, it will work:
echo "$(grep real < <({ time mysql -u admin -p123456foobar -h mydevreporting.com -N -e "SELECT * FROM metrics.account_use where account='foo' and profile='bar' order by date desc;"; } 2>&1)):localhost:$(date +'%m-%d-%y')"
As I'm seeing error messages:
./tst.sh: command substitution: line 40: syntax error near unexpected token `)'
./tst.sh: command substitution: line 40: `{ time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"} 2>&1)'
As you can see the echo "$(...) is inside this function outputOFF().
I've also tried escaping the braces \{, \}, which allows the variables to substitute, but somehow that command isn't working as it should.
echo "$(grep real < <(\{ time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"\} 2>&1)):localhost:${_dt}"
So, i'm stuck.
You are missing a ; in the {...} group expression, after "$exp" (see this documentation for why). Here is the corrected version:
echo "$(grep real < <({ time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"; } 2>&1)):localhost:${_dt}"
Less braces makes it more readable, at least for me.
result=$( { time mysql -u admin -p${_pw} -h ${host} -N -e "$exp"; } 2>&1 | grep real );
echo "${result}:localhost:${_dt}"
time is reporting on stderr. Thus the {} are neceessary to capture the output.
Or discarding the result, and only capture the result of time.
result=$( { time mysql -u admin -p${_pw} -h ${host} -N -e "$exp" >/dev/null; } 2>&1 )
echo ${result}":localhost:${_dt}"
The unquoted ${result} is printed without the newlines. Thus you can keep all information from time with the additional timestamp.

How to get the result of a command in a HERE_doc in Bash

I'm using the at command to schedule a job in the future.
DoCurlAt () {
if [ -n "${AuthToken:-}" ] ; then
$4 << 'EOF'
curl -s -H "${AuthHeader:-}" -H "$1" --data-urlencode "$2" "$3"
EOF
Exitcode=$?
fi
WriteLog Output Info "AT Output: $AtOutput Exitcode: $Exitcode"
}
How can I capture the result of the at in a variable called $AtOutput?
I tried with
AtOutput=$(bash $4 << EOF
curl -s -H "${AuthHeader:-}" -H "$1" --data-urlencode "$2" "$3"
EOF
)
But that does't really give any result.
Also tried with:
AtOutput=$(curl -s -H "${AuthHeader:-}" -H "$1" --data-urlencode "$2" "$3" | at "$4")
But I would prefer to use the HERE-doc.
The function is called with
DoCurlAt "$AcceptJson" "argString=$ArgString" "$ApiUrl/$ApiVersion/job/$JobUid/run" "$OneTime"
$OneTime ($4) could be for example "at 15:19 today" The output is mostly something like this:
job 7 at 2016-08-16 15:30
at writes to standard error, not standard output. Use the 2>&1 redirection to copy standard error to standard output first.
$ at_output=$( echo "cmd" | at "$when" 2>&1 )

Resources