debian bash / sh string execução

2

Estou preso com este pedaço de código aqui

user@server:~$ TEST="ssh [email protected] 'date; hostname -A; uname -a'"
user@server:~$ $TEST
bash: date; hostname -A; uname -a: Command not found.

Eu quero usar isso dentro de um script de shell e não sei qual é o problema. Ambos os sistemas são debian wheezy,

mas se executar o comando diretamente:

user@server:~$ ssh [email protected] 'date; hostname -A; uname -a'
Fre Aug 23 20:02:55 CEST 2013
otherserver.example.org
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 GNU/Linux

Então, qual é o grande problema aqui ?? Eu relay estou perdendo algo muito trivial, mas apenas não consigo descobrir ... Por favor ajude ...

A idéia por trás disso é que eu construo uma longa string dentro de um script e a executo remotamente em uma única sessão SSH (renomeando zfs snapshots todos em uma linha n.0 se torna n.1 e assim por diante)

Mas não funciona, quer que funcione ...

EDIT / UPDATE: Atualizado os exemplos para melhor compreensão da minha pergunta (de 'data; data; data' TO 'date; hostname -A; uname -a')

Obrigado por todas as respostas até agora. No primeiro eval funciona, mas parece ser preterido como mencionado pelos usuários. Então é meu trabalho descobrir isso de novo em como mudar isso.

A string que ele deve ser construída é semelhante a esta:

echo "Rearanging snapshots..."
        last_backup=7
        first_backup=0
        RENAME_STRING="'sudo zfs destroy $BACKUP_DATASTORE@n.$last_backup; "
        while [ $last_backup -gt $first_backup ]
        do
                RENAME_STRING=$RENAME_STRING"sudo zfs rename $BACKUP_DATASTORE@n.$(($last_backup - 1)) $BACKUP_DATASTORE@n.$last_backup"

            if [ $(($last_backup - 1 )) -gt $first_backup ]
            then
                    RENAME_STRING=$RENAME_STRING"; "
            else
                    RENAME_STRING=$RENAME_STRING"'"
            fi

            last_backup=$(($last_backup - 1 ))
    done

    #CURRENTLY SOLVED WITH EVAL as this one doesn't work...
    #remote_cmd=(/usr/bin/ssh "$BACKUP_USER@$HOST_TO" "$RENAME_STRING")
    #"${remote_cmd[@]}"
    eval /usr/bin/ssh $BACKUP_USER@$HOST_TO $RENAME_STRING

Então talvez vocês tenham uma maneira mais elegante de resolver isso?

EDIT2:

Esta saída é "OK"? (OK, como nos meios de não preterido, e bom trabalhar com?

user@server:~$ TEST="date ; hostname -A ; uname -a"
user@server:~$ ssh [email protected] <<< "$(printf '%s ' $TEST)"
Pseudo-terminal will not be allocated because stdin is not a terminal.
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Fre Aug 23 20:13:53 CEST 2013
otherserver.example.org 
Linux otherserver 3.2.0-4-amd64 #1 SMP Debian 3.2.46-1 x86_64 GNU/Linux

EDI3: Atualizado / aprimorado (?) enquanto o loop eval ainda é usado como < < < não vai funcionar no script ...

    
por Daywalker 23.08.2013 / 16:13

5 respostas

0

PROBLEMA ENCONTRADO

Eu comecei minha longa string com um singe ' e endet com um único '

AGORA eu mantenho todas essas citações simples ( ' ) sozinha, crie a string e adicione uma aspa dupla no final, um TODO TRABALHO!

#!/bin/sh
...
#[SOME_CODE_HERE]
...
echo "Rearanging snapshots..."
last_backup=7
first_backup=0
RENAME_STRING="sudo zfs destroy $BACKUP_DATASTORE@n.$last_backup; "
while [ $last_backup -gt $first_backup ]
do
        RENAME_STRING=$RENAME_STRING"sudo zfs rename $BACKUP_DATASTORE@n.$(($last_backup - 1)) $BACKUP_DATASTORE@n.$last_backup; "
        last_backup=$(($last_backup - 1 ))
done
/usr/bin/ssh $BACKUP_USER@$HOST_TO "$RENAME_STRING"

Alguém pode me explicar isso, por que não consigo definir aspas dentro da minha variável?

E essa construção agora funciona bem. Obrigado a todos pela vossa ajuda! Espero que minha resposta também ajude alguém! (a coisa ALL_CAPITAL será resolvida mais tarde;))

    
por 26.08.2013 / 12:33
3

A maneira sugerida de executar comandos locais remotamente via ssh não é usar eval. Isso é desencorajado. Como você está armazenando toda a linha em uma variável, em vez disso você poderia

mydate=$(date; date; date); 
ssh [email protected] bash <<< "$(printf 'echo %q ' "$mydate")"

O Eval só deve ser usado em sistemas legados que não fornecem ferramentas seguras como o exemplo que estou mostrando a você.

Isso produz exatamente o mesmo resultado que você estava executando esses comandos usando o shell interativo.

Espero que você tenha algumas ideias, pelo menos.

UPDATE para demonstrar como os comandos podem ser executados remotamente também, sem definir uma variável local.

ssh [email protected] bash <<< "$(printf '%s ' "whoami && ps aux")"
    
por 23.08.2013 / 16:54
2

Tente o comando eval do shell / bash:

$ help eval
eval: eval [arg ...]

Execute arguments as a shell command.

Combine ARGs into a single string, use the result as input to the shell,
and execute the resulting commands.

Exit Status:
Returns exit status of command or success if command is null.
    
por 23.08.2013 / 16:16
2

Não há razão para compor uma longa fila de comandos para executar via SSH. Basta fazer um roteiro permanente no host remoto chamado /usr/local/sbin/rotate_backups e chamá-lo com ssh $USER@$HOST 'sudo /usr/local/sbin/rotate_backups' .

Se você estava perguntando isso no "Unix & Linux" Stackexchange, então isso poderia ser uma questão interessante. No entanto, como administrador do sistema, suas metas devem ser de manutenção e segurança. Se você está tendo problemas para entender seu roteiro, seus colegas e sucessores irão xingá-lo.

    
por 23.08.2013 / 20:35
2

Tente isto:

user@server:~$ remote_cmd=(ssh [email protected] 'date; hostname -A; uname -a')
user@server:~$ "${remote_cmd[@]}"

Ele cria um array e o executa conforme sugerido no BashFAQ / 050 item 3.

    
por 23.08.2013 / 23:36