I have a command in quotes:
ssh -i "/home/$USER/$KEY" "$USER"#"$WORKER1IP" "echo 'if [[ `uname -a` == Darwin* ]]; then' >> /home/$USER/tachyon-0.5.0/conf/tachyon-env.sh"
The "uname" part has to be written literally, not executed. I tried using "\" before the 'uname' part, but I don't know how to close it. Can someone help please?
This should work:
ssh -i "/home/$USER/$KEY" "$USER"#"$WORKER1IP" "echo 'if [[ \"\$(uname -a)\" == Darwin* ]]; then' >> /home/$USER/tachyon-0.5.0/conf/tachyon-env.sh"
and this too:
ssh -i "/home/$USER/$KEY" "$USER"#"$WORKER1IP" "echo 'if [[ \`uname -a\` == Darwin* ]]; then' >> /home/$USER/tachyon-0.5.0/conf/tachyon-env.sh"
You can use $(...) with escaped $ in BASH:
ssh -i "/home/$USER/$KEY" "$USER"#"$WORKER1IP" "echo 'if [[ \$(uname -a) == Darwin* ]]; then' >> /home/$USER/tachyon-0.5.0/conf/tachyon-env.sh"
Use a here document instead, which simplifies the nested quotes.
ssh -i "/home/$USER/$KEY" "$USER#$WORKER1IP" <<EOF
echo 'if [[ $(uname -a) == Darwin* ]]; then' >> "/home/$USER/tachyon-0.5.0/conf/tachyon-env.sh"
EOF
Related
I don't use Bash very frequently but I need to work on a bit of Bash that has to make a curl request to a web service with a query string tail built from command arguments contained in the script command arguments variable $#. So if the command argument string is something like -e something -v -s somethingelse, then the query string that must be produced is e=something&v=blank&s=somethingelse.
At the moment my test script looks like this:
#!/bin/bash
set -e
echo "${#}"
query_string=""
for arg in "${#}" ; do
if [[ "${arg}" =~ "-" ]] ; then
query_string+="${arg}="
else
if [ -z "${arg}" ] ; then
query_string+="blank&"
else
query_string+="${arg}&"
fi
fi
done
echo "${query_string}" | tr -d '-'
and produces the incorrect output
e=something&v=s=somethingelse&
I'm not sure where I'm going wrong. Any suggestions would be appreciated.
How about:
#!/bin/bash
set -e
echo "${#}"
option=true
query_string=""
for arg in "${#}" ; do
if $option ; then
query_string+="${arg}="
option=false
else
if [[ "${arg}" =~ "-" ]] ; then
query_string+="blank&${arg}="
else
query_string+="${arg}&"
option=true
fi
fi
done
echo "${query_string::-1}" | tr -d '-'
Every iteration you have to check the previous arg to see if it was a switch, not a value:
#!/bin/bash
set -e
echo "${#}"
prev_arg=""
query_string=""
for arg in "${#}" ; do
if [[ $arg == -* ]] ; then
# Current arg is a switch and the previous one was also a switch
# which means the value for it is blank
if [[ $prev_arg == -* ]] ; then
query_string+="blank&"
fi
query_string+="${arg}="
else
query_string+="${arg}&"
fi
prev_arg="$arg"
done
echo "${query_string::-1}" | tr -d '-'
This produces the following output:
something -v -s somethingelse
e=something&v=blank&s=somethingelse
Trying to get this snippet working properly. I want to attempt an SFTP connection 3 times before breaking and exiting the shell. The catch is that there's a heredoc and sftp is not taking the heredoc as input when the connection is successful; the shell becomes interactive which I don't want.
count=0; until sftp -o StrictHostKeyChecking=no -i $key $server ; do ((count++)); [[ $count -eq 3 ]] && echo $count && break && exit 64; done; <<END
get docs/*
quit
END
I wouldn't write this this way at all (consider lftp rather than sftp), but:
count=0
until sftp -o StrictHostKeyChecking=no -i "$key" "$server" <<END
get docs/*
quit
END
do
if (( count++ >= 3 )); then echo "$count failures" >&2; exit 64; fi
END
Just make sure commands.txt contains your commands, one per line.
count=0
until sftp -o StrictHostKeyChecking=no -i "$key" -b commands.txt "$server"
do
((count++))
[[ $count -eq 3 ]] && echo $count && exit 64
done
I've recently started working with the getopts command in bash. I am confused as to why my script runs the dafult action "cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl" when arguments have been provided. I only want that to run if no arguments were passed to the shell script. I've used getopts:Std in perl where I was able to code somthing like:
unless ($opts{d}) {
do something...}
How would I code something like that in a shell script? Also, how would I code logic such as this:
if ($opts{c}) {
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -c
}
elsif ($opts{d} {
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -d
My code:
#!/bin/sh
while getopts cd name
do
case $name in
c)copt=1;;
d)dopt=1;;
*)echo "Invalid arg";;
esac
done
if [[ ! -z $copt ]] #Specifies what happens if the -c argument was provided
then
echo "CSV file created!"
cat "~/bin/Temp/log.txt" | ~/bin/Scripts/vpnreport/report.pl -c
fi
if [[ ! -z $dopt ]] #Specifies what happens if the -d argument was provided
then
echo "Debug report and files created"
cat ~bin/Temp/mag.txt | ~bin/Scripts/report.pl -d
fi
if [[ ! -z $name ]] #Specifies what happens if no argument was provided
then
echo "Running standard VPN report"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl
fi
shift $(($OPTIND -1))
My Output:
[~/bin/Scripts/report]$ sh getoptstest.sh
Running standard report
[~/bin/Scripts/report]$ sh getoptstest.sh -d
Debug report and files created
Running standard report
[~/bin/Scripts/report]$
The two getopts commands are vasty different from bash to perl and I just can't seem to get the hang of the bash varient even after reading several tutorials. Any help would be greatly appreciated!
On the final run of getopts, your variable (name) will be set to "?".
#!/bin/bash
while getopts abc foo; do :; done
echo "<$foo>"
Output of the above:
$ ./mytest.sh
<?>
$ ./mytest.sh -a
<?>
Insead, use elif, which is like Perl's elsif:
if [[ ! -z $copt ]]
then
# ...
elif [[ ! -z $dopt ]]
then
# ...
else
# ...
fi
Or test if [[ -z $copt && -z $dopt ]], or so forth. Other notes:
See the official if and case documentation in the Bash manual under "Conditional Constructs".
[[ ! -z $name ]] means the same as the more-direct [[ -n $name ]].
Use #!/bin/bash instead of #!/bin/sh, or switch off of [[ in favor of [. The double square bracket (and your use thereof) is specific to bash, and rarely works with sh.
I took Jeff's answer and rewrote my script so it works now:
#!/bin/bash
while getopts cd name
do
case $name in
c)carg=1;;
d)darg=1;;
*)echo "Invalid arg";;
esac
done
#Specifies what happens if the -c argument was provided:
if [[ ! -z $carg ]]
then
if [[ -z $darg ]]
then
echo "CSV created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -c
else
echo "Debug CSV created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -cd
fi
fi
#Specifies what happens if the -d argurment was provided:
if [[ ! -z $darg ]]
then
echo "Debug report created"
cat ~bin/Temp/log.txt | ~bin/Scripts/report.pl -d
#Specifies what happens if no argument was provided:
else
echo "Standard report created"
cat ~bin/Temp/logs.txt | ~bin/Scripts/report.pl
fi
Thank you again for your assistance!
I'm having some trouble with the != section of the if statement. Essentially this statement is valid as far as I'm aware, however executing this gives [: 1: !=: unexpected operator. I've tried executing using -n but for whatever reason, even if the output is blank, using -n still runs the echo command.
Any help on this is appreciated. I've attached the code snippet below.
#!/bin/sh
HOST=$1
USER="/scripts/whoowns $HOST | tr -d '\r'"
ssh -t $HOST -p 22 -l deehem "sh -c 'if [ "" != "\`$USER\`" ]; then echo "Username for $HOST: \`$USER\`"; fi' ; bash -login"
As you realised, "bla "" bla" is just two strings concatenated ("bla bla").
You can escape the ": \", but the standard [ test tool has an option specifically for this task:
-n STRING
the length of STRING is nonzero
-z STRING
the length of STRING is zero
Note: why do you have \`? That way the string is never going to be empty....
In regards to your "however executing this gives [: 1: !=: unexpected operator" problem, here is a solution:
Use bash -c instead of sh -c. The bash program seems to be better than sh at handling square brackets. For example:
ubuntu#ubuntu:/$ echo "antipetalous" | if [[ "antipetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi
match
ubuntu#ubuntu:/$ echo "antepetalous" | if [[ "antepetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi
no
ubuntu#ubuntu:/$ sh -c 'echo "antipetalous" | if [[ "antipetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi'
sh: 1: [[: not found
no
ubuntu#ubuntu:/$ bash -c 'echo "antipetalous" | if [[ "antipetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi'
match
ubuntu#ubuntu:/$ bash -c 'echo "antepetalous" | if [[ "antepetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi'
no
ubuntu#ubuntu:/$ sh -c 'echo "antepetalous" | if [[ "antepetalous" =~ "ti" ]]; then echo "match"; else echo "no"; fi'
sh: 1: [[: not found
no
ubuntu#ubuntu:/$
So ssh -t $HOST -p 22 -l deehem "sh -c 'if [ "" != ... would become ssh -t $HOST -p 22 -l deehem "bash -c 'if [ "" != ....
Thanks to pLumo at https://askubuntu.com/questions/1310106/sh-c-sh-not-working-when-using-if-statement-and-having-in-the-filena ("command line - sh -c '...' sh {} not working when using if statement and having ' in the filename - Ask Ubuntu").
OK, I can’t get this to work for some reason:
if /etc/mysql/my.cfn exist
then goto end;
else bash install.sh;
end exit;;
Check for non-existence and run install.sh if true.
[[ ! -e /etc/mysql/my.cfn ]] && bash install.sh
Here's a relatively literal translation:
if [ -e /etc/mysql/my.cfn ]; then
exit # Note: bash does not have a goto command
else
bash install.sh
fi
Or, eliminate the irrelevant then condition, and invert the test:
if [ ! -e /etc/mysql/my.cfn ]; then
bash install.sh
fi
The : command in bash with no arguments is a no-op, so you can use that in an if-body if you need to do nothing.
if something; then
:
else
do something else
fi
Of course, you'd normally want to write that as:
if ! something; then
do something else
fi
or
something || do something else
Your four lines in one line of Bash:
[[ -e /etc/mysql/my.cfn ]] && exit || bash install.sh
Did you mean my.cnf ?
(One) correct syntax is:
if [[ expression ]]; then
command
else
command
fi
The traditional style would be:
if test -f filename; then
command
fi