0

Currently I have below script to check if corresponding services are running on my server or not using some internal logic. Please find code snippet below:

MY_SERVER_ID=X22 //stored somewhere in profile of the servers

if [ "$MY_SERVER_ID" = "X11" -o "$MY_SERVER_ID" = "X22" -o "$MY_SERVER_ID" = "X33" ]
then

##do xx

     echo "  Service 1 : Running "

fi

if [ "$MY_SERVER_ID" = "X11" -o "$MY_SERVER_ID" = "X22" ]
then

##do xx

     echo "  Service 2 : Running "

fi

Now as all servers do not run all the services the If conditions become a lot more unreadable/ unnecessary complex. Currently I have 10+ servers and 8+ services where different services run on different servers. Also in future any service can be invoked/ start running on a particular node it wasn't running before in which case I have to go and change the script again.

I understand that in case of any change I definitely have to change the script and update in all the servers however I would like to make the process less painful than it already is.

I can implement something like an array that is defined at the start of the script to point out whether a given service runs on a particular node or not. Something I picked up from this question on stackoverflow.

I know multi dimensional arrays could be easily implemented in C but as I am quite new to shell scripting I would like to know if there is any possibility to make my script more readable and easily editable!!!

pOrinG
  • 896
  • 3
  • 13
  • 27
  • Shell doesn't have multi-dimensional arrays or other complex data structures. Do you really have to use shell for this? – Barmar Jul 12 '19 at 18:30
  • Well actually, BASH doesn't support multi-dimensional arrays, but ksh does (and also compound variable). That said it's possible to use several arrays to emulate them if I may say. Depends on the type of data you have in mind/need and their different relationship. – Andre Gelinas Jul 12 '19 at 18:34
  • bash supports associative arrays (maps) with `declare -A`. Values can be arrays. – Matthieu Jul 12 '19 at 18:40
  • 2
    Side note: why implement it yourself when you can use deployment tools like ansible and puppet and monitoring tools like zabbix or graphite or nagios or prometheus – KamilCuk Jul 12 '19 at 18:45
  • @Barmar Unfortunately I need to do it in shell only. Thanks for your answer. – pOrinG Jul 13 '19 at 13:07
  • @KamilCuk Noted will look into it. Thanks – pOrinG Jul 13 '19 at 13:08

1 Answers1

4

Since all your if checks are with the same variable, you can simplify it to case

case "$MY_SERVER_ID" in
X11|X22|X33)
    echo "Service 1 running" ;;
esac

bash doesn't have multi-dimensional arrays, but you could use a space-delimited string as a substitute for a second dimension, as long as the values are simple.

declare -A services
all_services=([X11]="1 2" [X22]="1 2" [X33]="1")
services=${all_services[$MY_SERVER_ID]}
for i in $services; do
    echo "Service $i running"
done

Another possibility is storing the data in a JSON file and using the jq utility to parse it and extract values. This more elaborate version is left as an exercise for the reader (I'm not really very experienced with this tool).

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I tried something like `for ((i=0; i<${n_services}; i++ )); do eval service_$i=$((1<<$i)); done` and testing with `.. if (( $((${!server} & ${!checkservice} )) > 0 )) .. ` but that is much too complex. I upvoted your short solution, that might be enhanced into a config file. – Walter A Jul 12 '19 at 21:06