enviando entrada de texto para uma tela separada

44

Estou tentando executar um servidor minecraft no meu servidor unRAID.

O servidor será executado no shell e ficará sentado, aguardando a entrada. Para pará-lo, preciso digitar 'stop' e pressionar enter, para salvar o mundo e sair graciosamente, e estou de volta ao shell. Tudo funciona se eu executá-lo via telnet na caixa NAS, mas quero executá-lo diretamente na caixa.

isto é o que eu tive anteriormente como primeira tentativa:

#define USER_SCRIPT_LABEL Start Minecraft server
#define USER_SCRIPT_DESCR Start minecraft server. needs sde2 mounted first
cd /mnt/disk/sde2/MCunraid
screen -d -m -S minecraft /usr/lib/java/bin/java -Xincgc -Xmx1024M -jar CraftBukkit.jar

MCunraid é a pasta na qual eu tenho o Craftbukkit.jar e todos os arquivos do mundo etc. Se eu digitar essa linha de tela diretamente, a tela será configurada desanexada e o servidor será iniciado. Se eu executar essa linha de dentro do script, não parece configurar uma tela

para parar o servidor, preciso 'digitar' em STOP e pressionar enter. Minha abordagem foi

screen -S minecraft -X stuff "stop $(echo -ne '\r')"

para enviar para a tela 'minecraft' o texto para e um retorno de carro. Mas isso não funciona, mesmo que eu o digite diretamente na linha de comando. Mas se eu 'screen -r' puder acessar a tela com o servidor em execução, digite 'stop' e ele será encerrado corretamente.

O servidor funcionará bem se eu fizer o telnet e fazê-lo manualmente, só preciso executá-lo sem estar conectado no meu computador remoto.

Richard Plumb
fonte
Isso parece certo . Qual é o conteúdo completo do script e como você o está executando? Produz alguma saída? Como você diz que screennão conseguiu iniciar? Tente adicionar set -xna parte superior do script (logo após a #!linha) e relate a saída do rastreio ao executar o script.
Gilles 'SO- stop be evil'
que é o conteúdo completo do script :) o comando screen funciona se eu digitá-lo diretamente, então eu acho que a minha questão principal é a parte parada
richard prumo
Você escreveu "Se eu executar essa linha de dentro do script, isso não parece configurar uma tela". Então a parte inicial funciona ou não? Caso contrário, veja meu primeiro comentário.
Gilles 'SO- stop be evil'
Estou tentando executá-lo como um script de usuário unMENU. Se eu tiver o script do usuário com esse comando de tela exato, nada acontecerá. Se eu digitar o comando screen em uma janela telnet, ele iniciará o servidor em uma tela como você esperaria. Então, acho que há alguma diferença que não entendo na maneira como os scripts de usuário unMENU são tratados.
Richard plumb
Agora estamos chegando a algum lugar. Atualize sua pergunta com informações sobre como você está usando unMENU. E tente adicionar duas linhas #!/bin/bashe set -xna parte superior do script e mostre-nos a saída de rastreamento do script. Pode ser necessário procurar na documentação unMENU para descobrir para onde vai essa saída.
Gilles 'SO- stop be evil'

Respostas:

40

Posso resolver pelo menos parte do problema: por que a stopparte não está funcionando? Experimentalmente, quando você inicia uma sessão de Tela no modo desanexado ( screen -d -m), nenhuma janela é selecionada; portanto, as entradas enviadas posteriormente screen -X stuffsão perdidas. Você precisa especificar explicitamente que deseja enviar as teclas pressionadas para a janela 0 ( -p 0). De qualquer forma, é uma boa ideia, caso você crie outras janelas nessa sessão da Tela por qualquer motivo.

screen -S minecraft -p 0 -X stuff "stop^M"

(A tela é convertida ^Mpara control-M, que é o caractere enviado pela Entertecla.)

O problema ao iniciar a sessão a partir de um script provavelmente está relacionado à unMENU.

Gilles 'SO- parar de ser mau'
fonte
1
bonito, funciona muito bem (pelo menos na linha de comando, vai cutucar os caras do unmenu mais tarde). Isso parece ter atraído muitas pessoas e é a primeira vez que vejo uma solução concreta. Eu só desejo que eu tinha pontos suficientes para votar-lo: D
richard prumo
Maldito seja! Funciona até a tela já está conectada, sem recolocá-la! O que é uma ótima maneira de enviar comandos para aplicativos simples de outros aplicativos no sistema. Obrigado! :)
Grzegorz Wierzowiecki
Nunca tive esse problema, provavelmente porque sempre planejei ter várias janelas (nomeadas) na minha sessão de tela e sempre escolho a janela pelo nome.
Ekevoo
Manual, para referência: -X Envie o comando especificado para uma sessão de tela em execução. Você pode usar a opção -S para especificar a sessão de tela se tiver várias sessões de tela em execução. Você pode usar a opção -d ou -r para instruir a tela a procurar apenas sessões de tela anexadas ou desanexadas. Observe que este comando não funciona se a sessão estiver protegida por senha.
KrisWebDev
3
isso não funciona para mim. Eu criei uma tela screen -d -m -S hie, em seguida, corro screen -S hi -p 0 -X stuff "cd <some_directory>^M"e não recebo nada como resultado ... ele envia "cd <some_directory> ^ M" como uma string e não interpreta "^ M" como tecla enter ...
Tanner Strunk
23

Primeiro, uma observação sobre como inserir facilmente novas linhas:

Apenas um aviso de que a $()construção retira novas linhas da saída do comando para que as linhas de saída possam ser usadas como argumentos para outros programas. Isso pode causar comportamento inesperado. Nesse caso, suponho que você esteja tentando enviar o equivalente ao Enterpressionamento de tecla. Embora o retorno de carro com o qual você está enviando \rnão seja listrado, existem várias maneiras mais fáceis de inserir esse caractere sem a necessidade de um comando extra.

  1. Você pode colocar uma nova linha regular entre aspas duplas

    screen -S minecraft -X stuff "stop
    "
    
  2. Ou você pode inserir o caractere em uma linha de terminal usando a sequência Ctrl+ v Enter. Será algo parecido ^Mcom o terminal, mas é um caractere de nova linha especial.

    screen -S minecraft -X stuff "stop^M"
    

Em segundo lugar, uma observação sobre o comportamento irregular da tela. ( Explicação e solução de Gilles )

Tela tem um problema ao aceitar entrada para uma sessão de tela que nunca foi anexada. Se você executar isso, haverá uma falha:

screen -d -m -S minecraft zsh
screen -S minecraft -X stuff "stop^M"
screen -r minecraft

Mas se você executar isso, funcionará:

screen -d -m -S minecraft zsh
screen -r minecraft (then disconnect with Ctrl-a-d)
screen -S minecraft -X stuff "stop^M"
screen -r minecraft

Por fim, você poderia usar o comportamento muito melhor em tmuxvez de screen.

O GNU-Screen é um multiplexador de terminal de fato há muitos anos, mas há muito deixa de ser desenvolvido e bugs e peculiaridades não estão sendo corrigidos. O Tmux está em desenvolvimento ativo, inclui muitos recursos que a tela não pode tocar e seu comportamento imediato é bastante mais intuitivo. Além disso, é melhor documentado. Veja como você converteria seu código:

# Start new detached tmux session with a named window pane running the java app
tmux new-session -d -n minecraft /usr/lib/java/bin/java [args]

# Send it keys to stop the mincraft server
tmux send-keys -t minecraft "stop^M"
Caleb
fonte
se eu alternar manualmente usando a tela -r, posso ver a tela e não há texto digitado. mesmo que o retorno do carro estivesse falhando, eu ainda deveria ser digitado 'stop'. Mas nada
Richard Plumb 28/05
se eu tiver um script com -r tela em uma linha, e depois filtrar material -X "parada ^ M", então ele não parar o servidor, mas também reclama com 'erro uknown opção r'
richard prumo
Eu testei aqui criando sessão de tela, depois usando o comando acima e ele funciona perfeitamente. Você consegue se conectar à sua sessão de tela usando screen -d -RR minecraft?
Caleb
sim, isso me conecta à tela. assim como a tela -r .. espera, se eu tentar a tela -S minecraft -X coisas "parar ^ M" e depois manualmente a tela -r, há um texto "stop" na tela.
Richard plumb
Funciona para mim. Talvez você tenha algo interessante na sua .screenrctela ou tenha várias sessões de tela abertas com esse nome e esteja enviando dados para a pessoa errada? screen -list?
Caleb
4

Peço desculpas por desenterrar este post antigo, mas isso teria me ajudado em meus empreendimentos se essas informações estivessem disponíveis no momento em que tive um problema semelhante. Há muitas perguntas sobre como enviar comandos de tela em um script bash. Como na pele de um gato, isso pode ser feito, mas eu gosto dessa maneira. Com isso, você pode enviar qualquer comando ou dizer qualquer coisa apenas chamando a função say_esta função.

#!/bin/bash

say_this()
{
    screen -S minecraft -p 0 -X stuff "$1^M"
}

say_this "say Saving world"
say_this "save-off"
say_this "save-all"
...

Isso é com ssh!

#!/bin/bash

say_this()
{
    # Dont forget to set NAME or whatever
    ssh -p 8989 192.168.1.101 screen -S $NAME -p 0 -X stuff \"$1^M\"
}

say_this "say test"
say_this "say !@#$%^&*()<>?This string will work!"
fuzzyfreak
fonte
Nice and Concise ... Bem-vindo ao L & L
eyoung100