Executa vários comandos ssh no mesmo shell (programaticamente)

1

OBSERVAÇÃO: Estou realmente procurando uma solução SSH-y aqui, mais do que bash-y uma.

Eu preciso executar uma série de comandos sobre o ssh, programaticamente. Há muitas maneiras de fazer isso, mas não consigo encontrar nenhuma que funcione com minhas restrições:

  • alguns dos comandos definem variáveis no shell. Portanto, eu não acho que posso fazer isso funcionar usando vários shells.

  • algumas dessas variáveis são funções, não valores normais, então eu não acho que posso simplesmente serializar a saída de env para "restaurar" o ambiente antigo.

  • Eu preciso acessar o código stdout, stderr e exit de cada comando separadamente. Isso dificulta encadear os comandos usando && ou ; . Acredito que isso também dificulte o uso de screen , porque não podemos dizer com segurança quando um comando é concluído.

  • Eu preciso de acesso em tempo real ao stdout, stderr, etc para que possamos gravar quando a saída ocorrer. (Eu uso "tempo real" para significar "nowish", não "hard real-time" ou qualquer coisa assim).

Atualizar

Por que preciso de uma única sessão bash? Como os comandos podem armazenar variáveis e funções arbitrárias no ambiente. Por exemplo, seria comum executar rvm , que é uma função bash adicionada por um comando executado anteriormente.

Por que não posso usar && ou ; ? Porque eu preciso do stdout e do stderr ou de cada comando individualmente, e isso iria misturá-los.

Por que não consigo usar a tela? Como queremos executar comandos automaticamente, não como parte de uma sessão interativa. Considere a dificuldade disso: eu teria que executar o comando com redirecionamento de formulário de entrada, saída via redirecionamento e, em seguida, scp os resultados de volta. Eu precisaria ecoar $? para obter o código de saída. Eu não seria capaz de timestamp o stderr / stdout. Eu não seria capaz de tempo limite do comando. E seria incrivelmente buggy.

    
por Paul Biggar 19.12.2011 / 04:45

4 respostas

2

Se você precisar de algo para capturar a saída, interagir com uma sessão de shell e / ou interagir com aplicativos pty como screen , tente escrever em uma biblioteca SSH de linguagem de nível mais alto, como o Ruby Net:SSH . Tem um pouco de curva de aprendizado, mas realizaria tudo que você precisa, acredito.

    
por 19.12.2011 / 04:59
2

I need to access the stdout, stderr and exit code of each command separately. This makes it difficult to chain the commands using && or ;.

Bem, não sei se realmente recomendo isso, mas você poderia escrever uma função de shell como esta:

function prefix ()
(
  PREFIX="$1"
  OUT=''
  while read -r ; do
    OUT="${OUT}${PREFIX}${REPLY}"$'\n'
  done
  echo "$OUT"
)

function run_cmd ()
{
  echo "Running command << $@ >> . . ."
  (
    ( ( "$@" ; echo "\$?: $?" >&3 ) | prefix 'STDOUT: ' >&3 ) 2>&1 \
    | prefix 'STDERR: '
  ) 3>&1
}

Em seguida, se ./foo.sh bar imprimir foo\nbar\n na saída padrão e baz\nbip\n no erro padrão e sair com o código 1, run_cmd ./foo.sh bar imprimirá algo como:

Running command << ./foo.sh bar >> . . .
$?: 0
STDOUT: foo
STDOUT: bar
STDERR: baz
STDERR: bip

Isso permitirá encadear uma sequência de comandos, desde que você use run_cmd para todos os códigos necessários para STDOUT / STDERR / exit-codes. (Mas como o comando em si é executado em subcamadas com cinco camadas de profundidade, não é possível usar run_cmd para executar qualquer comando que precise definir variáveis de ambiente para uso por outros comandos. Espero que você não tenha nenhum comando que ambos geram variáveis de saída e ?

    
por 19.12.2011 / 05:18
1

Você já deu uma olhada em pssh ? Abrange a maioria das suas necessidades e, com alguma criatividade e imaginação, pode ajudá-lo:

  • Pode enviar os comandos para vários servidores ao mesmo tempo
  • É capaz de produzir em tempo real
  • stdout e stderr podem ser salvos em arquivos separados
  • informa se o comando X no servidor Y foi bem-sucedido ou não
  • pode receber entrada de stdin e enviar para servidores
  • tem tempo limite configurável

E assim por diante ...

    
por 19.12.2011 / 08:39
0

Eu também acredito que a abordagem de Kyle seria a mais promissora. Se isso não funcionar, você poderia escrever seu script principal de uma maneira que ele fosse em um loop sem fim, onde ele procuraria por arquivos de comando que então cria e torna o código stdout, stderr e exit disponível em um formato utilizável para o seu propósito. .

Você então inseriria os arquivos de comando por meio de um canal alternativo, provavelmente apenas scp ou algo semelhante.

    
por 19.12.2011 / 05:56

Tags