Search code examples
bashsshgetopts

Bash script not reading from file


Purpose

This script is meant to copy one's public ssh identity file to many hosts that are listed in a file

Problem

The script is not properly reading IP's from the file. I believe this is because it is not reading the lines of the file. When I echo out the line (IP) it is reading, it is blank.

Code

#!/bin/bash
usage="Usage: $(basename "$0") [-h|-u|-i|-p|-f] -- Copys your identity key to a list of remote hosts
where:
-h Show this help text
-u Username of ssh user
-i Location of identity file (Default: /home/$USER/.ssh/id_rsa.pub)
-p Password (not secure)
-f Location of hosts file (Default: ./inventory)"

# Default location for files
CURR_DIR="$(cd "$(dirname "$0")" && pwd)"
HOSTS_FILE=${CURR_DIR}/inventory
IDENT_FILE=/home/$USER/.ssh/id_rsa.pub

# required_flag=false

while getopts 'hu:i:p:f:' option; do
  case $option in
    # Help
    h) echo "$usage"; exit;;
    # Hosts file
    f) HOSTS_FILE=$OPTARG;;
    # Password
    p) PASSWORD=$OPTARG;;
    # Indentity file
    i) IDENT_FILE=$OPTARG; echo "$IDENT_FILE";;
    # Username
    u) USERNAME=$OPTARG;;
    # Missing args
    :) printf "Option -%s\n requires an argument." "-$OPTARG" >&2; echo "$usage" >&2; exit 1;;
    # Illegal option
    \?) printf "Illegal option: -%s\n" "$OPTARG" >&2; echo "$usage" >&2; exit 1;;
  esac
done

shift "$((OPTIND-1))"
#  Decrements the argument pointer so it points to next argument.
#  $1 now references the first non-option item supplied on the command-line
#+ if one exists.

# if ! $required_flag && [[ -d $1 ]]
# then
#     echo "You must specify a hosts file. -h for more help." >&2
#     exit 1
# fi

while IFS= read -r line;
do
     echo "Current IP: " "$IP"
     echo "Current Username: " "$USERNAME"
     echo "Current Identity: " "$IDENT_FILE"
     echo "Current Hosts: " "$HOSTS_FILE"
     echo "Current Password: " "$PASSWORD"
     sshpass -p "$PASSWORD" ssh-copy-id -i "$IDENT_FILE" "$USERNAME"@"$IP"
done < $HOSTS_FILE

Output

$ ./autocopyid -u user -p password
Current IP:  
Current Username:  user
Current Identity:  /home/user/.ssh/id_rsa.pub
Current Hosts:  /home/user/inventory
Current Password:  password
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed

/usr/bin/ssh-copy-id: ERROR: ssh: Could not resolve hostname : Name or service not known

Solution

  • You are not using the variable line for anything. Assuming $HOSTS_FILE points to a file that contains one IP address per line, you now have the IP address in variable line instead of IP in your loop. But since you use the variable name IP in the body of the loop, you should use that in the read statement, too.

    So try

    while IFS= read -r IP
    

    instead of

    while IFS= read -r line