LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Bash script to read line by line and execute commands (https://www.linuxquestions.org/questions/programming-9/bash-script-to-read-line-by-line-and-execute-commands-911150/)

Striketh 10-31-2011 06:00 PM

Bash script to read line by line and execute commands
 
Hello,

I'm trying to figure out how to piece together a script that will do the following:

- Read a .txt file line by line. Each line will be the name of a server.
- SSH into each of these servers (keys are setup so no need for username/password). Just "ssh <servername>" will work.
- Execute a command on each server.
- Return the results in a coherent manner and place them in a text file. If possible, splitting the results up into separate text files based on $servername would be preferable.

I'm not much of a scripter, and I don't know enough to put this together properly. Any guidance would be highly appreciated.

Thanks for your time.

lior.okman 11-01-2011 01:00 AM

I am assuming the command is 'ls -rtl'. Substitute my assumption for your command.
Try this:

Code:

while read servername; do
      ssh $servername ls -rtl > $servername-result.txt
done < "the-servers.txt"


Nominal Animal 11-01-2011 04:31 AM

I personally would use
Code:

#!/bin/bash
while read server dummy ; do
    [ "${server//[#\/;]/}" = "$server" ] || continue
    [ "${#server}" -gt 0 ] || continue
    ssh "$server" "$@" </dev/null &>"$server.log" &
done
wait

The command to run is specified as a parameter to the script, and the list of servers as input, i.e.
Code:

./script ls -laF < servers.txt
The dummy variable makes sure the server will only contain the first word on each line. You may wish to extend the format later, so requiring the first word to be the server name makes sense.

The first test makes sure the server name does not contain hashes (#), slashes (/), or semicolons (;). Hash and semicolon are often used to indicate a comment line. Slash would make it impossible to create a file based on the server name. None of the three should occur in a server name or address anyway.

The second test makes sure the server name is not empty. Empty lines are common at the end of files, so handling them gracefully is a good idea.

The ampersand (&) backgrounds each ssh command, and the final wait waits until all ssh commands have completed. Since the ssh commands are done in parallel, I redirect the input to the ssh commands from /dev/null -- no user input is possible. It would not make sense to allow it anyway, because you could not tell which ssh command you were supplying input to.

Striketh 11-01-2011 10:35 AM

Quote:

Originally Posted by Nominal Animal (Post 4513066)
I personally would use
Code:

#!/bin/bash
while read server dummy ; do
    [ "${server//[#\/;]/}" = "$server" ] || continue
    [ "${#server}" -gt 0 ] || continue
    ssh "$server" "$@" </dev/null &>"$server.log" &
done
wait

The command to run is specified as a parameter to the script, and the list of servers as input, i.e.
Code:

./script ls -laF < servers.txt
The dummy variable makes sure the server will only contain the first word on each line. You may wish to extend the format later, so requiring the first word to be the server name makes sense.

The first test makes sure the server name does not contain hashes (#), slashes (/), or semicolons (;). Hash and semicolon are often used to indicate a comment line. Slash would make it impossible to create a file based on the server name. None of the three should occur in a server name or address anyway.

The second test makes sure the server name is not empty. Empty lines are common at the end of files, so handling them gracefully is a good idea.

The ampersand (&) backgrounds each ssh command, and the final wait waits until all ssh commands have completed. Since the ssh commands are done in parallel, I redirect the input to the ssh commands from /dev/null -- no user input is possible. It would not make sense to allow it anyway, because you could not tell which ssh command you were supplying input to.

This is fantastic - also, thank you for the explanation. I knew what I wanted to do, and had some ideas on how to do it, but while I could figure out X and Z, I couldn't think of how to put it all together for XYZ :)

That worked perfectly, though. Again, thanks a lot for your help!

cheesus 11-06-2011 11:38 AM

please click "mark solved".


All times are GMT -5. The time now is 12:34 PM.