El comando no se ejecuta a través de SSH

El comando no se ejecuta a través de SSH

Este script lo hice para un curso. Ejecuta comandos a través de ssh a partir de los argumentos del script, en una cantidad de servidores remotos especificados en un archivo:

#!/bin/bash

# The server file. Can be changed with the -f argument
SERVER_FILE='/vagrant/servers'

# The function to check if the chosen SERVER_FILE exists
filecheck() {
if [[ ! -e $SERVER_FILE ]]; then
  echo "The file $SERVER_FILE does not exist." >&2
  exit 1
fi
}

# The usage statement
usage() {
  echo "usage $0 -vsn -f FILE 'COMMAND'"
  echo "  -v Verbose mode"
  echo "  -s Run command as sudo on remote server"
  echo "  -n Dry run, commands not actually executed"
  echo "  -f FILE Selects a different file other than /vagrant/servers"
  exit 1
}

# The verbose mode text things
say() {
  if [[ $VERBOSE = 'true' ]]; then
    echo "$@"
  fi
}

# The ssh command
sshing() {
  ssh -o ConnectTimeout=2 $SERVER $@
}

# User executing the command should not be root
if [[ $UID -eq 0 ]]; then
  echo "You should not execute this script with sudo or as root" >&2
  echo "Use the -s argument if you want sudo powers" >&2
  exit 1
fi

# DRYMODE is sshing by Default
DRYMODE='sshing'

#check to see if file SERVER_FILE exists
filecheck

# The options for the script
while getopts vsnf: OPTION; do
  case $OPTION in
    v)
      echo "Verbose mode on"
      VERBOSE='true'
      ;;
    s)
      say "Sudo mode"
      SUDO='sudo'
      ;;
    n)
      say "Dry run mode"
      DRYMODE='echo'
      DRYRUN='DRY RUN: '
      echo "DRY RUN MODE ON: "
      echo
      ;;
    f)
      say "Different file mode"
      SERVER_FILE=${OPTARG}
      #check to see if file SERVER_FILE exists
      filecheck
      ;;
    *)
      usage
      ;;
  esac
done

echo

# shifts so that the options are removed from the list of arguments
shift $((OPTIND-1))

#Set a variable for the rest of the arguments, as a command
COMMAND="${@}"

# Checks if the user provided any arguments apart from the optinos
if [[ $# -eq 0 ]]; then
  usage
  exit 1
fi

# Executes the commands
for SERVER in $(cat ${SERVER_FILE}); do
  say "Executing ${COMMAND} on ${SERVER}:"
  $DRYMODE $DRYRUN $SUDO ${COMMAND} 2> /dev/null
  CMDEX=$?
  # if the exit status is 255, something is wrong with the server or is unreachable
  if [[ $CMDEX -eq 255 ]]; then
    echo "The server you're trying to reach does not exist or is unreachable. Aborting." >&2
    exit 1
  fi
  # if the exit status is non 0 and non 255, something is wrong with the command
  if [[ $CMDEX -ne 0 ]]; then
    echo "Invalid command ${COMMAND} or wrong syntax. Aborting." >&2
    exit 1
    # if the exit status is non 0 and non 255, something is wrong with the command
  fi
  say "Command ${COMMAND} executed successfuly."
done
exit 0

Y funciona perfectamente para comandos simples (como ls, pse incluso adduser test), pero simplemente se rompe si le doy cualquier comando que incluya una comilla doble A MENOS que ponga comillas simples todo el comando.

Ahora no sé si es un error en mi código o algo así, pero no puedo canalizar comandos a través de esto.

Entonces este comando no funciona:

[vagrant@admin01 vagrant]$ ./run-everywhere.sh -sv 'echo 1 | passwd --stdin test4'

Si escapo de la tubería con \| simplemente lo escribe literalmente como \|. Este otro comando tampoco funciona:

[vagrant@admin01 vagrant]$ ./run-everywhere.sh -sv 'echo "1" | sha256sum > file1'

EDITAR:

Encontré el problema con la tubería que no funciona: también tengo que escribir sudo DESPUÉS de la tubería si un comando necesita privilegios de sudo. Éste funciona de esta manera:

[vagrant@admin01 vagrant]$ ./run-everywhere.sh -sv 'echo 1 | sudo passwd --stdin test4'

Aunque todavía no puedo redirigir.

Respuesta1

Prueba esto:

sshing () {
  ssh -o ConnectTimeout=2 "$SERVER" "$@"
  # ................................^..^ crucial quotes
}
# ...
cmd="$*"
# ...
while read -r SERVER; do
  say "Executing ${COMMAND} on ${SERVER}:"
  $DRYMODE $DRYRUN $SUDO sh -c "${COMMAND}" 2> /dev/null
  # .....................11111.2..........2
  # 1. run with a shell to enable redirections and pipe
  # 2. crucial quotes
  # ...
done < "$SERVER_FILE"

Ejecutar el comando dentro de un shell con sudo permitirá que toda la canalización se ejecute con permisos elevados.

Además, debería dejar de utilizar nombres de variables en mayúsculas y minúsculas. Un día, accidentalmente sobrescribirás PATH y luego te preguntarás por qué tu script no funciona.

Respuesta2

Encontré el problema. Si ejecutaba el script con poderes sudo para tocar algunos archivos por sí solo, crearía los archivos bajo el nombre y grupo de root, lo que significaba que no tenía permisos sobre ese archivo.

información relacionada