Escribí el siguiente script bash:

#!/bin/bash

TIMEOUT="5"
SESSIONS="8"

function usage {
    echo "Usage: $(basename $0) -l servers.list -c COMMAND"
    echo ""
    echo "Options:"
    echo "   -l               :     Provide list containing hostnames/ips"
    echo "   -c               :     Command to run"
    echo "   -u [optional]    :     Run commands remotely as supplied user"
    echo "   -r [optional]    :     Connect to remote machine as root, run commands as supplied user"
    echo ""
    echo " **** \"-u\" is mandatory if \"-r\" is used ****"
    echo ""
}

while getopts ":l:c:u:r:" opt; do
    case $opt in
        l)
            LIST=$OPTARG
        ;;
        c)
            COMMANDS="$OPTARG"
        ;;
        u)
            USER=$OPTARG
            USERSWITCH="-l $USER"
        ;;
        r)
            RUSER=$OPTARG
            RUSERSWITCH="-l root"
            RUSERCMD="su - $USER -c '$COMMANDS'"
        ;;
        *)
            usage
            exit 1
        ;;
    esac
done

if [[ -z $LIST ]] || [[ -z $COMMANDS ]]; then
    echo "Error - not enough arguments have been supplied"
fi

if [[ -z $USER ]]; then
    /usr/bin/pssh -i -p $SESSIONS -t 100000000 -x "-oStrictHostKeyChecking=no" -O ConnectTimeout=$TIMEOUT -h $LIST "$COMMANDS"
    echo "user not supplied"
elif [[ ! -z $USER ]] && [[ ! -z $RUSER ]]; then
    echo "connecting as root running as user"
    /usr/bin/pssh $RUSERSWITCH -i -p $SESSIONS -t 100000000 -x "-oStrictHostKeyChecking=no" -O ConnectTimeout=$TIMEOUT -h $LIST "$RUSERCMD"
elif [[ ! -z $USER ]] && [[ -z $RUSER ]]; then
    echo "Connecting as supplied user"
    /usr/bin/pssh $USERSWITCH -i -p $SESSIONS -t 100000000 -x "-oStrictHostKeyChecking=no" -O ConnectTimeout=$TIMEOUT -h $LIST "$COMMANDS"
fi

Básicamente envuelve el comando "paralelo-ssh" y permite algunas funciones más que se requieren en mi lugar de trabajo, como proporcionar una lista o ejecutar comandos como un usuario específico.

El guión funciona perfectamente.

El único problema que tengo es con el comando proporcionado después del modificador "-c"; debe colocarse dentro ("") o los espacios en el comando harán que la variable obtenga solo la primera palabra en el comando.

¿Cómo debo editar la secuencia de comandos para que pueda obtener lo que esté después de -c incluso si no se ingresa ("")?

0
Itai Ganot 19 feb. 2018 a las 14:32

2 respuestas

La mejor respuesta

Podrías hacer algo como esto (gracias @JohnKugelman por los útiles consejos):

c)
    shift "$((OPTIND-2))"
    cmd=$(printf "%q " "$@")
    break
  • OPTIND: el índice del siguiente argumento a procesar
  • $((OPTIND-2)): el número de argumentos hasta la opción -c
  • shift "$((OPTIND-2))": cambia todo a la opción -c
  • printf "%q " "$@": imprime los argumentos restantes ($@ - solo el comando porque todo lo demás se ha desplazado)
  • %q: help printf -> quote the argument in a way that can be reused as shell input
3
PesaThe 19 feb. 2018 a las 18:20

No estoy muy seguro de por qué se enfrenta a este problema, pero usar variables como ${COMMANDS} siempre es una buena práctica, ya que mantiene todas las variables intactas.

Dado que está utilizando una variable después de -c, debería utilizar RUSERCMD="su - $USER -c '${COMMANDS}'"

0
Rohit Kumar 19 feb. 2018 a las 12:10