Nested Case statement in shell script | Getting Syntax error - linux

I am trying to run below shell script but i am getting syntax error.
script.sh env1 ManagedSvr1
line 29: warning: here-document at line 6 delimited by end-of-file (wanted `EOF')
line 30: syntax error: unexpected end of file
#!/bin/bash
case "$1" in "env1")
ssh weblogic#hostname1 << EOF
case "$server" in
"ManagedSvr1")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr1/logs/ManagedSvr1.log
;;
"ManagedSvr2")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log
;;
esac
;;
"env2")
ssh weblogic#hostname2 << EOF
case "$server" in
"ManagedSvr1")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr1/logs/ManagedSvr1.log
;;
"ManagedSvr2")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log
;;
esac
;;
esac

Your Here Docs specify EOF to end them (<< EOF) but you never have an EOF to end them. Note that EOF doesn't mean End of File, it means the string 'EOF'. https://en.wikipedia.org/wiki/Here_document has examples.
I'm not sure what you're hoping to accomplish, but it looks to me that you need to specify which file to tail. Are you hoping to pass the inner case into the remote shell on the server you're sshing into? It would simplify your code to set your filename and servername first and then ssh and execute the command. Actually, I don't see much purpose in your inner case statements anyway. Instead of wrapping everything in the 'env' case, you could just set the hostname to a variable. And then the "servername" can just be interpolated into the filesystem path. something like this seems like a simple approach:
#!/bin/bash
case "$1" in
env1)
hostname="hostname1"
;;
env2)
hostname="hostname2"
;;
esac
echo ssh weblogic#$hostname tailf /app/Oracle/Middleware/domains/dq/servers/$servername/logs/$servername.log
Seems to work simply and straight forward:
servername=ManagedSvr1 ./t.sh env1
ssh weblogic#hostname1 tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr1/logs/ManagedSvr1.log
Take out the "echo" to actually execute the ssh.

You actually don't need "HERE" docs, per say, you're using one case statement which is taking standard input to your SSH command. take single quotes as input to ssh This lets you do multiline input in peace. Quoting your "EOF" and terminating it, is also acceptable usage.
#!/bin/bash
case "$1" in
"env1")
ssh -tt weblogic#hostname1 <<< '
case "$server" in
"ManagedSvr1")
cat /var/log/syslog
;;
"ManagedSvr2")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log
;;
esac '
;;
"env2")
ssh -tt weblogic#hostname2 <<< '
case "$server" in
"ManagedSvr1")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr1/logs/ManagedSvr1.log
;;
"ManagedSvr2")
tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log
;;
esac '
;;
esac
This would be an easier way to manage the script. Especially as you're not utilising remote user change: Lets you set all your variables locally, and then just connect and execute the single command.
#!/bin/bash
server="$2"
case "$1" in
"env1")
hostname="hostname1"
case "$server" in
"ManagedSvr1")
remote_command=$(tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr1.log)
;;
"ManagedSvr2")
remote_command=$(tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log)
;;
esac
;;
"env2")
hostname="hostname2"
case "$server" in
"ManagedSvr1")
remote_command=$(tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr1/logs/ManagedSvr1.log)
;;
"ManagedSvr2")
remote_command=$(tailf /app/Oracle/Middleware/domains/dq/servers/ManagedSvr2/logs/ManagedSvr2.log)
;;
esac
;;
*)
exit 1
;;
esac
if [[ $? == 0 ]]
then ssh weblogic#$hostname $remote_command
fi

Related

Shell script with case statement and loop for not working

trying to connect in servers list and execute some commands, this script dont execute second step (AIX)
SO=uname -s
for server in $(cat maq)
do
case $SO in
Linux)
echo "Connecting in $server"
ssh $server
echo "my system is $SO"
"exit"
;;
AIX)
echo "Connecting in $server"
ssh $server
echo "my system is $SO"
"exit"
;;
esac
done
They execute "my server is Linux" for all case choice! Any Help?
(Edited to make it more clear)
You seem to confuse the local OS with the remote OS. The former won't change during the cycle, only the latter. Here is a complete example.
LocalOs="$(uname -s)"
case "$LocalOs" in
Linux)
echo "Local OS is $LocalOs";
;;
AIX)
echo "Local OS is $LocalOs";
;;
*)
echo "Local OS is $LocalOs";
;;
esac
while read server; do
RemoteOs=$(ssh </dev/null "$server" 'uname -s')
case "$RemoteOs" in
Linux)
echo "OS on $server is $RemoteOs"
;;
AIX)
echo "OS on $server is $RemoteOs"
;;
*)
echo "OS on $server is $RemoteOs"
;;
esac
done <"maq"
Edit: also you misunderstood how ssh works in a script. This doesn't work:
ssh remoteuser#remotehost
commands to be executed on remotehost
exit
This works:
ssh remoteuser#remotehost <<EOF
commands to be executed on remotehost
EOF
Simpler case:
ssh remoteuser#remotehost 'command(s) to be executed on remotehost'

unrecognized service for my init.d

here is my full code, I just use following code:
case "$1" in
st)
echo 450 > /sys/class/backlight/intel_backlight
;;
stop)
echo
;;
rst)
echo; echo 450 > /sys/class/backlight/intel_backlight
;;
*)
echo "Usage: $0 {st|stop|rst}"
exit 1
;;
esac
why it raise this error
the reason is my init.d file has not "x" permission, so I need first chmod 755 /etc/init.d/brightness before running it
You may want to consider base your init script on the skeleton which live in /etc/init.d. Your script is probably inpcomplete.

Case statement not working in my shell script

I'm trying to write a shell script for Mac OSX Mountain Lion (10.8.2). However, no matter what I try, I can't get the switch statement to work. He is a very simplified version of the script:
#!/bin/bash
while getopts "ei" opt; do
case $opt in
e)
echo "Got option e"
;;
i)
echo "Got option i"
;;
\?)
echo "Invalid option: -$opt"
;;
esac
done
No matter what I try, I don't get any output. Any ideas? I've done scripts like this in the past.
You might be passing the options incorrectly don't forget the -
script.sh -e
Note you should also exit after an invalid option:
\?)
echo "Invalid option: -$opt"
exit 1
;;
Try replacing
\?)
echo "Invalid option: -$opt"
;;
with:
*)
echo "Invalid option: -$opt"
;;

GETOPTS passing option to create find function

Im trying desperately finding the solution for my Getopts
For example
#!/bin/bash
while getopts ":a:b:" opt; do
case $opt in
a) find / $OPTARG >&2 ;;
b) 2>/dev/null >&2 ;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
and then as output example
./somefile.sh -a *txt -b
or
./somefile.sh -b -a *txt
but then i want to make sure i can upgrade it further, for examples find only sh files, or
something else.
Its not easy to find, but i hope someone could help me.

Prevent ssh from breaking up shell script parameters

I have a script, which is essentially a wrapper around an executable by the same name on a different machine. For the sake of example, i'll wrap printf here. My current script looks like this:
#!/bin/bash
ssh user#hostname.tld. printf "$#"
Unfortunately, this breaks when one of the arguments contains a space, e.g. i'd expect the following commands to give identical outputs.:
~$ ./wrap_printf "%s_%s" "hello world" "1"
hello_world1_
~$ printf "%s_%s" "hello world" "1"
hello world_1
The problem gets even worse when (escaped) newlines are involved. How would I properly escape my arguments here?
Based on the answer from Peter Lyons, but also allow quotes inside arguments:
#!/bin/bash
QUOTE_ARGS=''
for ARG in "$#"
do
ARG=$(printf "%q" "$ARG")
QUOTE_ARGS="${QUOTE_ARGS} $ARG"
done
ssh user#hostname.tld. "printf ${QUOTE_ARGS}"
This works for everything i've tested so far, except newlines:
$ /tmp/wrap_printf "[-%s-]" "hello'\$t\""
[-hello'$t"-]
#!/bin/sh
QUOTE_ARGS=''
for ARG in "$#"
do
QUOTE_ARGS="${QUOTE_ARGS} '${ARG}'"
done
ssh user#hostname.tld. "${QUOTE_ARGS}"
This works for spaces. It doesn't work if the argument has an embedded single quote.
Getting quoting right is pretty hard and doing it in bash (in a general and robust way) almost impossible.
Use Perl:
#!/usr/bin/perl
use Net::OpenSSH;
my $ssh = Net::OpenSSH->new('user#hostname');
$ssh->system('printf', #ARGV);
Based on the answers from Koert and Peter Lyons, here a wrapper for ssh; i call it "sshsystem". (also available at https://gist.github.com/4672115)
#!/bin/bash
# quote command in ssh call to prevent remote side from expanding any arguments
# uses bash printf %q for quoting - no idea how compatible this is with other shells.
# http://stackoverflow.com/questions/6592376/prevent-ssh-from-breaking-up-shell-script-parameters
sshargs=()
while (( $# > 0 )); do
case "$1" in
-[1246AaCfgKkMNnqsTtVvXxYy])
# simple argument
sshargs+=("$1")
shift
;;
-[bcDeFIiLlmOopRSWw])
# argument with parameter
sshargs+=("$1")
shift
if (( $# == 0 )); then
echo "missing second part of long argument" >&2
exit 99
fi
sshargs+=("$1")
shift
;;
-[bcDeFIiLlmOopRSWw]*)
# argument with parameter appended without space
sshargs+=("$1")
shift
;;
--)
# end of arguments
sshargs+=("$1")
shift
break
;;
-*)
echo "unrecognized argument: '$1'" >&2
exit 99
;;
*)
# end of arguments
break
;;
esac
done
# user#host
sshargs+=("$1")
shift
# command - quote
if (( $# > 0 )); then
# no need to make COMMAND an array - ssh will merge it anyway
COMMAND=
while (( $# > 0 )); do
arg=$(printf "%q" "$1")
COMMAND="${COMMAND} ${arg}"
shift
done
sshargs+=("${COMMAND}")
fi
exec ssh "${sshargs[#]}"
The easiest and quickest is to just use Bash's Quoting Parameter Transformation: ${parameter#Q}. This can automatically applied during array expansion with ${array[#]#Q}, but when using the builtin argument array, the name and the brackets are dropped, so it becomes ${##Q}. Therefore the original script only needs 4 characters added to it to work.
#!/bin/bash
ssh user#hostname.tld. printf "${##Q}"
Now any escaping will work, even terminal colors like this:
./wrap_printf "%s\e[39m\e[49m\n" $'\e[30m\e[42mBlack on Green' "Just Normal Text"

Resources