Comando não executando por SSH

2

Eu fiz este script para um curso. Executa comandos através do ssh dos argumentos do script, em vários servidores remotos especificados em um arquivo:

#!/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

E ele funciona perfeitamente para comandos simples (como ls , ps e mesmo adduser test ), mas apenas quebra se eu der a ele qualquer comando que inclua uma aspas duplas A MENOS que eu cite o comando inteiro .

Agora eu não sei se é um bug no meu código ou algo assim, mas não posso canalizar comandos através disso.

Portanto, este comando não funciona:

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

Se eu escapar do pipe com \ | apenas literalmente escreve como \ |. Este outro comando também não funciona:

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

EDITAR:

Eu encontrei o problema com a tubulação não funcionando: Eu tenho que escrever sudo APÓS o pipe também se um comando precisar de privilégios de sudo. Este aqui funciona assim:

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

Ainda não consigo redirecionar.

    
por iamAguest 27.08.2018 / 14:30

2 respostas

0

Tente isto:

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"

Executar o comando dentro de um shell com sudo permitirá que todo o pipeline seja executado com permissões elevadas.

Além disso, você deve perder o hábito de usar nomes de variáveis ALLCAPS. Um dia, você acidentalmente substituirá o PATH e depois se perguntará por que seu script está quebrado.

    
por 27.08.2018 / 15:29
0

Encontrou o problema. Se eu rodasse o script com poderes sudo para tocar alguns arquivos por conta própria, ele criaria os arquivos sob o nome e o grupo do root, o que significava que eu não tinha permissões nesse arquivo.

    
por 27.08.2018 / 16:09