Enviar comando para a tela desanexada e obter a saída

12

Eu tenho procurado para encontrar uma maneira de enviar um comando para uma sessão de tela desanexada. Por enquanto, tudo bem. Isto é o que eu vim com:

$ screen -S test -p 0 -X stuff 'command\n'

Este comando funciona como deveria. Mas também gostaria que a saída ecoasse diretamente na frente dos meus olhos (não há necessidade de um .logarquivo ou algo assim, eu só quero a saída).

Usando o screen -Lcomando, não é uma opção.

Robin
fonte
Por que tem que ser screen? Não é para isso que os processos filhos são feitos?
Anko

Respostas:

10

Use um tubo primeiro a entrar:

mkfifo /tmp/test

Use um operador de redirecionamento. Redirecione a saída do comando para / tmp / test, por exemplo, da seguinte maneira:

screen -S test -p 0 -X stuff 'command >/tmp/test\n'

Então em outra concha

tail -f /tmp/test.

Observe que você também pode redirecionar mensagens de erro usando o operador 2> & 1 .

Exemplo

Conforme solicitado nos comentários, vamos assumir que temos um script php que aceita a entrada do usuário e imprime a carga do servidor na entrada de "status":

# cat test.php
<?php
  $fp=fopen("php://stdin","r");
  while($line=stream_get_line($fp,65535,"\n")) 
  {
    if ($line=="status") {echo "load is stub";} 
  } 
  fclose($fp);
?>

Você cria dois fifos:

 # mkfifo /tmp/fifoin /tmp/fifoout

Você chama uma tela:

screen

Em outro console, vamos chamá-lo de console 2 e você descobrir o nome da sua tela:

# screen -ls
There is a screen on:
        8023.pts-3.tweedleburg  (Attached)
1 Socket in /var/run/screens/S-root.

No console 2, você envia o comando para a tela:

 # screen -S 8023.pts-3.tweedleburg -p 0 -X stuff 'php test.php </tmp/fifoin >/tmp/fifoout\n'

você vê o comando aparecendo na tela. Agora, no console 2, você pode enviar comandos para o seu processo php:

echo "status" >/tmp/fifoin

e leia a partir dele:

# cat /tmp/fifoout
load is stub
Thorsten Staerk
fonte
1
Desculpe, mas isso não funciona. Se estou enviando um comando para a tela como 'command> / tmp / test', o processo deve oferecer suporte à sintaxe> / tmp / test ... E não.
Robin
Para mim, funciona, observe que eu coloquei "teste" como o nome da sua tela. Você pode descobrir o nome da sua tela com o comando screen -ls. Além disso, "comando" deve ser substituído pelo seu comando real, eu testei com o comando ls. Além disso, eu testei com o shell bash.
Thorsten Staerk
Eu sei disso. E isso não funciona. Por exemplo, inicie um script PHP em uma janela de tela que, por exemplo, responda a um comando "status", que retorna a carga atual do servidor, por exemplo. É o que estou tentando fazer.
Robin
então você vai precisar de tubos bidirecionais, eu estou adicionando este para a minha resposta
Thorsten Staerk
6

Eu tenho um script python que monitora várias sessões de tela desanexada e captura a saída de cada uma (quando comandos de utilização como free, top -bn2, iostat são enviados periodicamente via 'stuff').

Em vez de redirecionar para um arquivo e, assim, gerenciar pelo menos um arquivo por sessão de tela desanexada ... Simplesmente redireciono para qualquer tty / pts que minha sessão pai esteja usando.

Etapa 1: inicie uma nova sessão de tela (com um nome legível por humanos) no modo desanexado.

$ screen -dmS chad 

Etapa 2: Envie seus comandos (usarei o comando 'free -g' junto com 'uname -r') via material. É importante especificar a janela que você deseja usar (no nosso caso, a primeira e única janela) com -p.

$ screen -r chad -p0 -X stuff "free -g; uname -r" 

Etapa 3: A etapa acima envia apenas o texto do comando. Também precisamos enviar um retorno de carro para esta sessão de tela desanexada para que o shell execute nosso comando. O caractere ASCII 015 é um retorno de carro na maioria dos sistemas * nix.

$ screen -r chad -p0 -X eval "stuff \015"

Etapa # 4: Redirecione a saída de nossa sessão de tela desanexada para nossos atuais tty / pts:

$ screen -r chad -p0 -X hardcopy $(tty)

A saída da Etapa 4 será mais ou menos assim:

$ free -g; uname -r
             total       used       free     shared    buffers     cached
Mem:             7          1          6          0          0          0
-/+ buffers/cache:          0          7
Swap:            1          0          1
2.6.32-358.el6.x86_64

Embora isso pareça um pouco envolvido, o processo é facilmente programável. Com o python, eu posso analisar a saída da Etapa 4 e capturar apenas os dados que me interessam.

Escolhendo um cenário simples como obter detalhes de IP, escrevi um exemplo de script para demonstrar os conceitos acima. Sinta-se livre para substituir e mexer como achar melhor.

Exemplo de script python para obter detalhes de IP de uma sessão de tela desanexada:

#!/usr/bin/python

import pexpect, time

#spawn a new bash session
session = pexpect.spawn('/bin/bash')
#send screen commands
session.sendline('screen -dmS netIP')
session.sendline('screen -r netIP -p0 -X stuff "ifconfig eth0 | grep -v eth0 | head -1"')
session.sendline('screen -r netIP -p0 -X eval "stuff \\015"')
#give the command a chance to execute before reading the output of our detached screen
time.sleep(0.1)

#use the output of the uname command as our string to expect
session.sendline('screen -r netIP -p0 -X hardcopy $(tty); $(uname)')
session.expect('Linux')

#parse the output - only concerned with the 'inet' line
output = session.before.split('\n')
for o in output:
    if 'inet' in o:
        print o

#kill the screen
session.sendline('screen -r netIP -p0 -X quit')
time.sleep(0.1)

session.close()

Script acima em ação:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
chad_walker
fonte
Gosto desta resposta muito melhor do que a aceita, porque ela não depende da tela estar no estado "prompt de shell", mas funciona com o que estiver sendo executado nessa tela também.
Guntram Blohm apoia Monica
No entanto, requer a saída para caber na tela. Eu encontrei screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log offpara trabalhar ainda melhor nesse cenário.
Guntram Blohm apoia Monica
-1
screen -S myscreen

screen -R myscreen -X exec command

Exemplo:

screen -R myscreen -X exec top
aod
fonte