Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash reading from file and parsing each line [duplicate]

Tags:

linux

bash

I need to manage updates of a particular software on several customers' linux servers. The updates are provided by sending .tar.gz files to each server and inflating it overwriting the old software files.

I've put the customers' server list in a txt file like this:

user1@customer-server-1-address:22:/path/to/software/server1:NULL:Customer1name

user2@customer-server-2-address:2222:/path/to/software/server2:/etc/vpnc/client1.conf:Customer2name

user3@customer-server-3-address:22:/path/to/software/server3:NULL:Customer3name

Char ":" acts as field separator; field 1 is the server address, 2 is port, 3 is path to software, 4 is used to tell if a VPN tunnel is to be enabled first, 5 is customer name.

I've managed to create the following script:

#!/bin/bash

[...]

while IFS=':' read -ra array; do
    if [ "${array[3]}" != "NULL" ]; then
        echo
        echo "### USING VPN CONF '${array[3]}' FOR SERVER '${array[0]}'... ###"
        sleep 1
        #vpnc ${array[3]}
        TUNNEL1=$(ifconfig | grep -o eth0)
        TUNNEL2='eth0'

        if [ "$TUNNEL1" = "$TUNNEL2" ]; then
          echo "### TUNNEL IS UP ###"

          scp -P${array[1]} $FILENAME.gz ${array[0]}:${array[2]}
          scp -P${array[1]} $FILELIST ${array[0]}:${array[2]}

          ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && cat '${array[2]}'/'$FILELIST' | cpio --quiet -H ustar -o -0 -L -F '${array[2]}'/'$BACKUP_FILENAME
          ssh -p${array[1]} ${array[0]} 'gzip '${array[2]}'/'$BACKUP_FILENAME

          ssh -p${array[1]} ${array[0]} 'tar -C '${array[2]}' -xf '${array[2]}'/'$FILENAME.gz
          ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && mkdir -p '$REMOTE_BACKUP_DIRECTORY' && rm -f '$FILELIST' && mv -f '$BACKUP_FILENAME.gz $REMOTE_BACKUP_DIRECTORY

          echo "### SERVER '${array[0]}' UPDATED ###"
          #vpnc-disconnect
          sleep 1
        else
          echo "### VPN ERROR IN SERVER '${array[4]}' ###"
        fi
    else
        echo

        scp -P${array[1]} $FILENAME.gz ${array[0]}:${array[2]}
        scp -P${array[1]} $FILELIST ${array[0]}:${array[2]}

        ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && cat '${array[2]}'/'$FILELIST' | cpio --quiet -H ustar -o -0 -L -F '${array[2]}'/'$BACKUP_FILENAME-${array[4]}
        ssh -p${array[1]} ${array[0]} 'gzip '${array[2]}'/'$BACKUP_FILENAME-${array[4]}

        ssh -p${array[1]} ${array[0]} 'tar -C '${array[2]}' -xf '${array[2]}'/'$FILENAME.gz

        ssh -p${array[1]} ${array[0]} 'cd '${array[2]}' && mkdir -p '$REMOTE_BACKUP_DIRECTORY' && rm -f '$FILELIST' && mv -f '$BACKUP_FILENAME-${array[4]}.gz $REMOTE_BACKUP_DIRECTORY

        echo "### SERVER '${array[4]}' UPDATED ###"
        echo
    fi;
done < "$CUSTOMER_SERVERS_FILE"

$CUSTOMER_SERVERS_FILE is the container file as described earlier, $FILENAME.gz is the update package, $FILELIST is the list of the files to update. Other variables set for other purposes.

Problem is, this whole thing is effectively running only for the first customer in my $CUSTOMER_SERVERS_FILE. The lines above the first are being skipped, and I can't tell why. Any hints? Thank you.

EDIT: As an answer to the duplicate objection, being the script rather large I didn't think of any link between the while and ssh objects. I was rather thinking more of a syntax error. However, I can still delete the question if asked to do so.

like image 248
Seether Avatar asked Dec 04 '25 14:12

Seether


1 Answers

This happens because your while read loop and ssh both read from stdin.

You can fix it by using /dev/null as ssh's stdin:

ssh host cmd  < /dev/null 
like image 177
that other guy Avatar answered Dec 07 '25 04:12

that other guy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!