1

I want a script which will restart the defined services on their respective servers. I want to pass parameter as below to the script: eg:

sh execute.sh [server1:nginx,mysqld],[server2:mysqld,apache2],[server3:mongodb,apache2]

So it should go to server1 and restart nginx and mysqld service over there. Then to server2 and should restart mysqld and apache over there and so on so.

I have the script like below:

#!/bin/bash
# create an array of server:services
a=($(echo "$1" | gawk 'BEGIN { FS="[]],[[]" } ; { print $1, $2, $3 }' | tr -d '[]'))
# add a for loop here to iterate values in array with code below
for var in "${a[@]}" ; do
# get server name
server1=$(echo $a[0] | cut -d ':' -f1)
# get your services as space separated
servs1="$(echo $a[0] | cut -d ':' -f2 | tr ',' ' ')"
# loop your services
for s in $servs1; do
  ssh $server1 "service $s restart"
done
done

The above script is only able to grep the first server name and service. Please help to get others.

Original question:

2
  • You might want to learn puppet. Commented Oct 15, 2013 at 19:29
  • 1
    Why do you want the argument to look like that? Is it just because you thought it looks good, or because you have some other script which generates those strings? Because it's usually easier to follow the standard way of doing things, which in the case of bash scripts, is to pass one argument per argument, with a lot less punctuation. (eg. restart server1:nginx,mysqld server2:mysqld,apache server3:mongodb,apaches) Commented Oct 15, 2013 at 20:22

2 Answers 2

2

Arrays, IFS, and for loops oh my! Million ways to do this. I love arrays so I used them. I wasn't sure if you wanted to call each service individually or all at once so I did it individually. Also You can also easily build a single command to run from this method. You will notice I am changing IFS to handle the commas. I removed the brackets and the , between the servers so you would call it like this:

CALL SCRIPT:

./test2 server1:nginx,mysqld server2:sshd,apache2

CODE:

    #!/bin/bash
    #-- samples: server1:nginx,mysqld server2:mysqld,apache2
    declare -a list
    read -a list <<< "${@}"
    echo ${list[@]}

    for (( i=0; i<${#list[@]}; i++ )) ;do

        IFS=' '
        server=$(echo ${list[$i]} | cut -d: -f1)
        services=$(echo ${list[$i]} | cut -d: -f2)

        IFS=,
        for each in $services ;do
            echo "Go To $server: restart $each"
        done

    done

OUTPUT:

    Go To server1: restart nginx
    Go To server1: restart mysqld
    Go To server2: restart sshd
    Go To server2: restart apache2
Sign up to request clarification or add additional context in comments.

2 Comments

You can use the shell's built-in "${var#*:}" parameter substitutions instead of the unattractive $(echo | cut).
Good point! I was doing it quick and dirty here .. Actually I haven't done it with arrays like that... do you want to show me by editing ?
1

Why don't you simply

while read host services; do
    for service in $services; do
        ssh "$host" service "$service" restart
    done
done <<____HERE
    server1 nginx mysqld
    server2 mysqld apache
    server3 mongodb apache2
____HERE

3 Comments

Sorry, @tripleee I have solved my problem after posting the question here. But I don't know how to close this question.
You should select someone's answer or post your own and select that as the correct answer. Hence when people search for this they can get some insight
I like Tripleee's answer but I would assume you have to feed it a file. which wasn't asked here. It seemed like you wanted a one liner type of thing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.