comando SSH com o redirecionamento de arquivo não está funcionando

2

Eu quero o resultado do comando a seguir para redirecionar para um arquivo no servidor remoto, como eu quero apenas linhas exclusivas no meu arquivo authorized_keys :

ssh [email protected] awk '!seen[$0]++' /root/.ssh/authorized_keys

Eu tentei o seguinte sem sucesso:

ssh [email protected] "awk '!seen[$0]++' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"

ssh [email protected] "awk \'!seen[$0]++\' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"

ssh [email protected] '(awk \'!seen[$0]++\' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp)'

Meus googles falharam comigo ... alguma idéia sobre o que estou fazendo errado?

    
por VenomFangs 04.12.2014 / 20:32

3 respostas

3

Tente isso (eu testei na minha máquina e parece funcionar - bem, eu não tinha nenhum duplicado para remover, mas ...):

ssh [email protected] "awk '!seen[\
ssh [email protected] "awk '!seen[\%pre%]++' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"
]++' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp"

Suas tentativas de " -quote não funcionaram porque você não usou a barra invertida de $ em $0 , o que levou a expansão para algo como bash .

Sua tentativa de citar uma única citação não funcionou porque 'foo\'some thing\'foo' não significa o que você acha que faz. \ -escapes não são interpretados dentro de strings entre aspas simples. Então, isso é, na verdade, citações desequilibradas e dois argumentos; o primeiro é foo\some e o segundo é thing'foo , mas não está completo porque o último ' inicia uma nova cadeia entre aspas simples.

O escape de conchas pode ser uma dor, especialmente com escape duplo. Enviar um script de shell (com sftp , scp , etc.) primeiro e, em seguida, executar isso geralmente é mais fácil.

    
por 04.12.2014 / 20:48
0

Eu vou aceitar a resposta de derobert porque ela me deu a informação que eu precisava. Ainda tive problemas, o que acho que pode ter sido o meu comando awk , que substituí com uma abordagem alternativa. Segue-se o que fiz para garantir que o meu ficheiro authorized_keys no servidor remoto tinha apenas entradas exclusivas:

ssh [email protected] "sort /root/.ssh/authorized_keys | uniq > /root/.ssh/temp"
ssh [email protected] "mv -f /root/.ssh/temp /root/.ssh/authorized_keys"
    
por 04.12.2014 / 21:14
0

Aqui está tudo o que você precisa saber sobre como citar algo para protegê-lo da expansão do shell e da divisão de palavras:

  1. Coloque todos os outros além de apóstrofos entre apóstrofos. Por exemplo, do not se torna 'do not' .
  2. Use barras invertidas para escapar de apóstrofos, ou seja, ' se torna \' .
  3. Divida sua sequência em apóstrofos e outros caracteres, aplique as duas regras anteriores e concatene os resultados. Por exemplo, don't se torna 'don'\''t' .

Com essas regras gerais, o comando da sua pergunta pode ser corretamente citado da seguinte forma:

ssh [email protected] 'awk '\''!seen[$0]++'\'' /root/.ssh/authorized_keys > /root/.ssh/authorized_keystemp'

Existem maneiras mais legíveis de citar a mesma string, mas essa abordagem é geralmente aplicável e fácil de verificar visualmente como correta.

Eu me pego fazendo isso com a freqüência suficiente para que eu escrevesse uma função shell / script para fazer isso por mim, e eu a uso o tempo todo. Aqui está:

#!/bin/sh -

# shellquote foo => foo
# shellquote foo&bar => 'foo&bar'
# shellquote foo'bar => 'foo'\''bar'
shellquote() {
  local input="$1"
  local output=""
  local backslash='\'
  local apostrophe="'"
  if [ -z "${input}" ]; then
    # Empty string => pair of apostrophes
    output="''"
  fi
  while [ -n "${input}" ]; do
    case "${input}" in
    "'"*)
      # Escape the apostrophe.
      output="${output}${backslash}${apostrophe}"
      input="${input#${apostrophe}}"
      ;;
    *"'"*)
      # Quote everything before the first apostrophe, and then escape
      # the apostrophe.
      output="${output}${apostrophe}${input%%${apostrophe}*}${apostrophe}${backslash}${apostrophe}"
      input="${input#*${apostrophe}}"
      ;;
    *[!+,./0-9:=@A-Z_a-z-]*)
      # There are no apostrophes, but at least one character needs quoting.
      # So quote the entire word.
      output="${output}${apostrophe}${input}${apostrophe}"
      input=""
      ;;
    *)
      # Nothing needs quoting. Output everything literally.
      output="${output}${input}"
      input=""
    esac
  done
  printf '%s' "${output}"
}

main() {
  local sep=''
  for arg; do
    printf '%s' "${sep}"
    shellquote "${arg}"
    sep=' '
  done
}

main "$@"
    
por 05.12.2014 / 01:56