Eu tenho uma if
declaração para calcular arquivos e excluir todos, exceto os três arquivos mais recentes. Mas eu quero executar este comando remotamente. Como posso combinar ssh
com uma if
condição?
Eu tentei isso, mas sem sucesso.
#!/bin/bash
ssh -t test@192.168.94.139 "cd /var/www/test.com/backup ;
if [ $(ls | wc -l) -lt 3 ]
then
echo "Less"
else [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]
echo "deleted"
fi"
O erro que recebi:
ls: não pode acessar * .tgz: esse arquivo ou diretório não existe
command-line
bash
ssh
Janith
fonte
fonte
$(
)
parte do comando é executada pelo shell local antes mesmo de iniciar ossh
comando. Isso é verdade tanto quando$(
)
autônomo quanto quando é encerrado por"
s. No entanto, se$(
)
estivesse dentro de'
s, não seria executado pelo shell local.Respostas:
NOTA: de fato, existem duas camadas para a pergunta aqui. Uma é 'Eu quero executar uma tarefa não trivial em um servidor remoto acessível via SSH'. O outro é: 'Estou tentando passar uma cadeia complexa para um comando, e o argumento acaba sendo diferente do que eu pretendia'. Estou respondendo à pergunta de baixo nível sem discutir se a abordagem usada é "correta" (conveniente, sem tendência a erros, segura etc.) para resolver a de alto nível. Conforme indicado pelas outras respostas e comentários, possivelmente não é.
Sua linha de comando está quase certa; você só precisa alterar um pouco as citações.
O principal problema é que as seqüências de aspas duplas são expandidas pelo shell local e, portanto, as
$(...)
partes serão avaliadas no sistema local. Para passá-los para o sistema remoto, você deve colocar o script entre aspas simples.Você também tem algumas aspas incorporadas. No seu script original, existem os argumentos para os dois
echo
s; se você alterar a cotação externa para aspas simples, será o script awk. Isso efetivamente resulta na omissão das aspas, o que não incomoda osecho
s, mas atrapalha o script do awk, pois o sinal maior que se torna o redirecionamento de saída. Portanto, depois de alterar as aspas externas para aspas simples, altere-as para aspas duplas.Este é o seu script com a citação corrigida. O script pode ter outros problemas, eu apenas corrigi a sintaxe.
fonte
/var/www/test.com/backup
a uma variável chamada "BACKUPDEST" ecd $BACKUPDEST
você pode me dizer como fazer isso?BACKUPDEST
? Se isso acontecer no lado remoto, inclua-o normalmente no script. Se você deseja defini-lo localmente (por exemplo, calculá-lo no script local ou transmiti-lo como argumento da linha de comando), você pode alterar a primeira linha para, por exemplo"cd $BACKUPDEST"' ;
- o shell expande a parte entre aspas duplas, mantém as aspas simples parte intacta, concatena os dois e passa o resultado como o último argumento parassh
."cd '$BACKUPDEST'"' ;
caso o caminho nessa variável contenha alguma estranheza (por exemplo, um espaço). Novamente: apenas dizendo que isso pode ser feito dessa maneira, não que isso deva ser feito dessa maneira.Sim, você pode executar scripts complexos via
ssh
Este exemplo usa um documento do bash here para gerar a cadeia de comandos. De qualquer forma, a passagem de scripts via ssh é suscetível a erros, porque é difícil citar e escapar variáveis (lembre-se da barra invertida antes dos comandos). Se o script ficar muito complexo, é melhor copiá-lo
scp
e executá-lo no host de destino.Não tentei corrigir seu script , mas aqui está um exemplo de como a contagem e a exclusão de um host remoto podem funcionar:
O
ls -t *.tgz
não vai funcionar, uma vez que o englobamento está acontecendo apenas no sistema local. Também usandols
para arquivos de contagem não é uma boa ideia, uma vez que também retorna entradas como.
,..
e diretórios.fonte
syntax error near unexpected token elif'
,elif [ $(ls -t |awk 'NR >3'|xargs rm -f) ]; then'
;
falta na primeira declaração if. Mas eu não consertei seu script! Existem muitas outras questões, por exemplo, ols *.tgz
$(...)
dentro de uma sequência de aspas duplas, então o shell local a avaliou. Escapá-lo como\$(...)
mostrado no primeiro exemplo, ou usar aspas simples em todo o script, evita que o shell local o expanda, sendo enviado para o sistema remoto, expandido pelo shell remoto e o script funciona como pretendido.printf
expandir variáveis - isso ainda será mais fácil de gerenciar do que tentar escapar de todas as variáveis do shell. Além disso, evitaria a necessidade de usarcat
apenas para capturar o documento aqui em uma variável!Eu acho que todo esse material de citação complicado é prova suficiente para não usá-lo, mas usar um script. Se você deseja evitar várias
ssh
conexões, canalize o script para o outro host e deixe executar em um comando:Arquivo local, diga
myscript.sh
:Então:
Ou (evitando um uso inútil de gato ):
Isso canaliza o script local
myscript.sh
para o lado remoto, onde é redirecionado para um arquivo (temporário)/tmp/ms.sh
, executado e finalmente removido.Nota: Não verifiquei o script original quanto a erros, mas só queria mostrar a ideia. Nenhuma citação propensa a erros é necessária e todos os comandos no script são executados no lado remoto.
fonte
ssh user@host bash <myscript.sh
.mktemp
ou algo similarmente seguro.Eu preferiria colocar o script na instância remota e apenas executá-lo através do ssh, mas aqui está minha sugestão de como isso pode ser feito da maneira que você deseja:
Notas:
-lt
é substituída por-le
.eval
- constrói o comando concatenando argumentos.\"
dentro da$COMMAND{1..3}
expressão, mas decido adicioná-las.fonte