using case statement in bash to pass in only arguments - bash

I have the following code in my script:
case "$1" in
(-h)
display_help
exit 0
;;
(start)
start_services
;;
(stop)
stop_services
;;
(*)
display_help
exit 0
;;
esac
I want to be able to pass in an argument when one of these commands is called. For example, I want to start only a users service. I would issue the following command:
./services.sh start users
If I just enter:
./services.sh start
That works as expected, all services are started. However, if I issue the command with a service attached to it, like described above, it still starts all services, not just that service. The code in the start_services() function looks for an argument to start that service.
How do I get it so that it only starts that one service within the case statement?

If start_services looks for an argument, you have to pass it:
start_services "$2"

Related

Why is my function only being partially executed when embedded in a case statement?

I have a .conf file that I am calling in my main script, which contains a case statement.
In this file, I have a series of ssh commands that I am combining into a single variable/array/function (I've tried multiple methods) to be executed when the condition is met in my case statement. For context, this is a script to auto-shutdown clients.
~/variables.conf
#!/bin/sh
CLIENT_1="ssh admin#1.1.1.1 shutdown -r now"
CLIENT_2="ssh admin#1.1.1.2 shutdown -r now"
CLIENT_ALL() { $CLIENT_1 ; $CLIENT_2 ; }
#also tried with similar results
#CLIENT_ALL="$CLIENT_1; $CLIENT_2"
#CLIENT_ALL=($CLIENT_1 $CLIENT_2)
To make sure this portion of code is working and the variables are passing, I run a test.sh and execute from CLI.
~/variables.test.sh
#!/bin/sh
. ~/variables.conf
CLIENT_ALL
Great, everything works. My two clients restart successfully - ssh keys stored so no prompt to enter password.
But when this is called from my case statement, things go wrong:
~/script.sh
#!/bin/sh
. ~/variables.conf
case $1 in
trigger1)
logger <message> #this is working fine
printf <message> | msmtp <email> #this is working fine
CLIENT_ALL
;;
*)
logger "Unrecognized command: $1"
;;
esac
What happens when this triggers: it logs, it sends an email but only the first client gets the ssh command to reboot. It passes the first variable $CLIENT_1 and then stops. I've tried a variety of ways to define and package the ssh commands, as well as a variety of ways to call them in the case statement, but always with the same results. I am certain that there is something about case statement rules/logic that I am overlooking that will explain this behavior and a correct way to make this work.
For my use-case, I need to use a case statement. My goal is to have a single command in the case statement so that the main script doesn't have to be modified - only the .conf needs to be updated if clients are added/removed.
Any help would be greatly appreciated.

shell script to run java cmd in loop and start it in parallel with input parameter

New to shell scripting, trying to run a java program in parallel with port specified as input.
For example ./Test.sh 8080 8081 --> Desired result would be to run script twice with 2 ports . i think " & " is to make it run in PARALLEL ?
Help/ guidance would be appreciated.
#!/bin/bash
PORT=$*;
if [ $# -eq 0 ]
then
echo "No arguments supplied"
fi
for i in $PORT
do
java -DpropertySource=~/Downloads/app.properties -jar APP.jar
-Dserver.port="$PORT" &
done
There are a few bugs here:
1) $1 will only contain the first parameter. You will need $* to contain more than one. (And given that you want the variable to contain multiple ports, it would then be more helpful to call the variable PORTS.)
2) You cannot have the whitespace around the = in a variable assignment in bash.
3) You are looping over i but not using that variable inside the loop. Where you have -Dserver.port="$PORT" you should instead use your loop variable i.
4) You are missing a line continuation character \ at the end of the java ... line (ensure that there is no whitespace after it).
5) The command separator ; at the end of the first line is redundant (although it does not actually harm).
6) Where you are testing for wrong usage, the script will issue the warning but carry on regardless. You need to put an exit statement there. It is good practice to give a non-zero exit value in the event of a failure, so exit 1 is suggested here.
Putting these together:
#!/bin/bash
PORTS=$*
if [ $# -eq 0 ]
then
echo "No arguments supplied"
exit 1
fi
for i in $PORTS
do
java -DpropertySource=~/Downloads/app.properties -jar APP.jar \
-Dserver.port="$i" &
done
Regarding the &, it will launch the command in the background, so that execution of the script will continue (including then reaching the end and exiting) while the command that was launched may still be running. So yes, your java instances listening on the different ports will then be running in parallel.

Run command in background and capture result later (Bash)

Similar to these questions (1) (2), I'm wanting to run a command in a background process, carry on processing, then later use the return value from that command.
I have one function in my script that takes particularly long, so I would like to run it first before the rest of the setup so that there is less of a delay when the return value of that script is given, but currently the return value doesn't get captured.
What I've tried:
if [ $LAZY_LOAD -eq 0 ]; then
echo "INFO - Getting least loaded server in background. Can take up to 30s."
local leastLoaded=$( getLeastLoaded ) &
fi
# Other setup stuff that doesn't use leastLoaded...
# setup setup setup....
if [ $LAZY_LOAD -eq 0 ]; then
echo "INFO - Waiting for least loaded server to be retrieved before continuing"
wait
fi
echo "INFO - Doing stuff with $leastLoaded."
doThingWithLeastLoaded $leastLoaded
getLeastLoaded definitely works without the &, so I'm sure this is a concurrency issue.
Thanks!
According to bash manual:
If a command is terminated by the control operator &, the shell executes the command in the background in a subshell.
So your local command would not affect the current shell.
I'd suggest like this:
do-something > /some/file &
... ...
wait
var=$( cat /some/file )

Start stop restart linux script like well known programs (apache,openvpn,squid etc)

Does anyone know a tutorial how to control the execution of a script (created) like we control squid, the basic run and stop command?
Example:
#squid start;
#squid stop;
#squid restart;
Something like this:
cmd=$1
case "$cmd" in
start)
# code to start the service
;;
stop)
# code to stop the service
;;
restart)
# code to restart
;;
...
*) echo Invalid command: "$cmd"
exit 1
;;
esac

SLES HA. How to run bashscript from cluster?

I want to run simple unmount command before starting my "file-system" service on my node.
Is there any way to call bash script as cluster service?
You can run any script as a cluster service. The script needs to be LSB compliant: i.e. needs to know start, stop, restart, status, etc. I usually copy something simple from /etc/init.d and modify it for myself.
Put the script in /etc/ha.d/resource.d
Test it from command line
# sh /etc/ha.d/resource.d/start (see if it unmounts)
Now if you haven't already, create resource group. Add in all your resources into the same group. Then add your new script in the resource group. You can configure constraints so that all resources depend on your first application resource to run first.
That's about it. You don't need to actually have anything configured for stop and status except "exit" since you just want your script to run once (to unmount)
Here is a script that might work in /etc/ha.d/resource.d
#!/bin/sh
#
# description: testapp auto start-stop script.
#
. /etc/rc.status
case "$1" in
start)
umount [filesystem]
;;
stop)
;;
reload*|restart*|force-reload*)
;;
status)
;;
*)
echo "options: start|stop|reload|restart|force-reload|status"
exit 1
;;
esac
exit
Hope that helps
I have an outline of my steps for building clusters plus an ebook here:
http://geekswing.com/geek/building-a-two-node-sles11-sp2-linux-cluster-on-vmware/

Resources