Enviar entrada de texto a una pantalla separada

44

Estoy tratando de ejecutar un servidor de Minecraft en mi servidor no RAID.

El servidor se ejecutará en el shell y luego se sentará allí esperando la entrada. Para detenerlo, necesito escribir 'detener' y presionar enter, y luego salvará el mundo y saldrá con gracia, y estoy de vuelta en el shell. Todo eso funciona si lo ejecuto a través de Telnet en la caja NAS, pero quiero ejecutarlo directamente en la caja.

Esto es lo que tuve previamente como primer intento:

#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 es la carpeta donde tengo el Craftbukkit.jar y todos los archivos del mundo, etc. Si escribo esa línea de pantalla directamente, la pantalla se desconecta y el servidor se inicia. Si ejecuto esa línea desde el script, no parece configurar una pantalla

para detener el servidor, necesito 'escribir' en STOP y luego presionar enter. Mi enfoque fue

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

para enviar a la pantalla 'minecraft' el texto detenido y un retorno de carro. Pero eso no funciona, incluso si lo escribo directamente en la línea de comando. Pero si 'screen -r' puedo acceder a la pantalla con el servidor en ejecución, escriba 'stop' y se apagará correctamente.

El servidor funciona bien si hago telnet y lo hago manualmente, solo necesito ejecutarlo sin estar conectado desde mi computadora remota.

richard plumb
fuente
Esto se ve bien . ¿Cuál es el contenido completo del script y cómo lo está ejecutando? ¿Produce alguna salida? ¿Cómo sabes que screenno pudo comenzar? Intente agregar set -xen la parte superior de la secuencia de comandos (justo después de la #!línea) e informe el resultado del seguimiento cuando ejecute la secuencia de comandos.
Gilles 'SO- deja de ser malvado'
es decir el contenido completo de la secuencia de comandos :) el comando de pantalla funciona si lo escribo en forma directa, por lo que creo que mi principal problema es la parte de tope
Richard plomada
Usted escribió "Si ejecuto esa línea desde el script, no parece configurar una pantalla". Entonces, ¿la parte de inicio funciona o no? Si no es así, vea mi primer comentario.
Gilles 'SO- deja de ser malvado'
Estoy tratando de ejecutarlo como un script de usuario unMENU. Si tengo el script de usuario con ese comando de pantalla exacto, no pasa nada. Si escribo el comando de pantalla en una ventana de Telnet, inicia el servidor en una pantalla como es de esperar. Así que creo que hay alguna diferencia que no entiendo en la forma en que se manejan los scripts de usuario de UNMENU.
Richard Plumb
Ahora estamos llegando a alguna parte. Actualice su pregunta con información sobre cómo está utilizando unMENU. E intente agregar dos líneas #!/bin/bashy set -xen la parte superior del guión, y muéstrenos el resultado de seguimiento del guión. Es posible que deba buscar en la documentación de unMENU para saber a dónde va esa salida.
Gilles 'SO- deja de ser malvado'

Respuestas:

40

Puedo resolver al menos parte del problema: por qué la stopparte no funciona. Experimentalmente, cuando inicia una sesión de pantalla en modo separado ( screen -d -m), no se selecciona ninguna ventana, por lo que la entrada enviada más tarde screen -X stuffsimplemente se pierde. Debe especificar explícitamente que desea enviar las pulsaciones de teclas a la ventana 0 ( -p 0). De todos modos, esta es una buena idea, en caso de que cree otras ventanas en esa sesión de Pantalla por cualquier motivo.

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

(La pantalla se traduce ^Ma control-M, que es el carácter enviado por la Entertecla).

El problema al iniciar la sesión desde un script probablemente esté relacionado con unMENU.

Gilles 'SO- deja de ser malvado'
fuente
1
hermoso, funciona muy bien (al menos desde la línea de comandos, empujará a los chicos del menú más tarde). Esto parece haber arrojado a bastantes personas y es la primera vez que veo una solución concreta. Solo desearía tener suficientes puntos para votar: D
richard plumb
¡Maldita sea! Funciona incluso si la pantalla ya está conectada, ¡sin volver a conectarla! ¿Cuál es una excelente manera de enviar comandos a aplicaciones simples desde otras aplicaciones en el sistema? ¡Gracias! :)
Grzegorz Wierzowiecki
Nunca tuve este problema, probablemente porque siempre planeé tener varias ventanas (con nombre) en mi sesión de pantalla, y siempre elijo la ventana por nombre.
Ekevoo
Manual, para referencia: -X Enviar el comando especificado a una sesión de pantalla en ejecución. Puede usar la opción -S para especificar la sesión de pantalla si tiene varias sesiones de pantalla ejecutándose. Puede usar la opción -d o -r para indicarle a la pantalla que busque solo sesiones de pantalla adjuntas o separadas. Tenga en cuenta que este comando no funciona si la sesión está protegida con contraseña.
KrisWebDev
3
Esto no funciona para mí. He creado una pantalla con screen -d -m -S hiy luego ejecuto screen -S hi -p 0 -X stuff "cd <some_directory>^M"y no obtengo nada como resultado ... simplemente envía "cd <some_directory> ^ M" como una cadena y no interpreta "^ M" como la tecla enter ...
Tanner Strunk
23

Primero, una nota sobre cómo ingresar nuevas líneas fácilmente:

Solo un $()aviso de que la construcción elimina las nuevas líneas de la salida del comando para que las líneas de salida se puedan usar como argumentos para otros programas. Esto puede causar un comportamiento inesperado. En este caso, supongo que está tratando específicamente de enviar el equivalente de la Enterpulsación de tecla. Si bien el retorno de carro con el que está enviando \rno se raya, hay varias formas más fáciles de ingresar ese carácter sin la necesidad de un comando adicional.

  1. Puede colocar una nueva línea regular dentro de sus comillas dobles

    screen -S minecraft -X stuff "stop
    "
    
  2. O puede ingresar el carácter en una línea terminal usando la secuencia Ctrl+ v Enter. Esto se verá algo así como ^Men la terminal, pero es un personaje especial de nueva línea.

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

En segundo lugar, una nota sobre el comportamiento errático de la pantalla. ( Explicación y solución de Gilles )

La pantalla tiene un problema al aceptar la entrada a una sesión de pantalla que nunca se ha adjuntado. Si ejecuta esto, habrá fallado:

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

Pero si ejecuta esto, 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 último, podría usar el mejor comportamiento en tmuxlugar de screen.

GNU-Screen ha sido un multiplexor de terminales de facto durante muchos años, pero ha dejado de desarrollarse y los errores y las peculiaridades no se están solucionando. Tmux está en desarrollo activo, incluye muchas características que la pantalla no puede tocar, y su comportamiento fuera de la caja es bastante más intuitivo. Además, está mejor documentado. Así es como convertirías tu 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
fuente
si cambio manualmente usando screen -r, puedo ver la pantalla y no se ingresa ningún texto. incluso si el retorno del carro fallaba, aún debería escribir 'stop'. Pero nada
richard plumb
si tengo un script con pantalla -r en una línea, y luego pantalla -X "detiene ^ M", entonces detiene el servidor, pero también se queja con 'error uknown option r'
richard plumb
Probé aquí creando sesión de pantalla, luego usando el comando anterior y funciona perfectamente. ¿Puede conectarse a su sesión de pantalla usando screen -d -RR minecraft?
Caleb
Sí, eso me conecta a la pantalla. también lo hace screen -r ... espera, si intento screen -S minecraft -X cosas "stop ^ M" luego manualmente screen -r, hay un texto 'stop' en la pantalla.
Richard Plumb
Funciona para mi. ¿Quizás tienes algo funky en tu .screenrco tienes un montón de sesiones de pantalla abiertas con ese nombre y entonces estás enviando datos a la incorrecta? screen -list?
Caleb
4

Pido disculpas por desenterrar esta publicación anterior, pero esto me habría ayudado en mis esfuerzos si esta información estuviera disponible en el momento en que tuve un problema similar. Hay muchas preguntas sobre cómo enviar comandos de pantalla en un script bash. Al igual que con la piel de gato, esto se puede hacer, pero me gusta de esta manera. Con esto, puede enviar cualquier comando o decir cualquier cosa simplemente llamando a la función say_this.

#!/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"
...

Esto es con 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
fuente
Agradable y conciso ... Bienvenido a U&L
eyoung100