Senden von Texteingaben an einen getrennten Bildschirm

44

Ich versuche, einen Minecraft-Server auf meinem unRAID-Server auszuführen.

Der Server wird in der Shell ausgeführt und wartet dort auf Eingaben. Um es zu stoppen, muss ich 'stop' eingeben und die Eingabetaste drücken, und dann wird die Welt gerettet und ich bin wieder in der Shell. Das alles funktioniert, wenn ich es per Telnetting in die NAS-Box starte, es aber direkt auf der Box ausführen möchte.

Das hatte ich vorher als ersten Versuch:

#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 ist der Ordner, in dem ich das Craftbukkit.jar und alle Weltdateien usw. habe. Wenn ich diese Bildschirmzeile direkt eingebe, wird der Bildschirm getrennt eingerichtet und der Server gestartet. Wenn ich diese Zeile innerhalb des Skripts ausführe, scheint sie keinen Bildschirm einzurichten

Zum Stoppen des Servers muss ich STOP 'eingeben' und dann die Eingabetaste drücken. Mein Ansatz war

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

Senden Sie auf dem Bildschirm 'minecraft' den Text Stop und einen Wagenrücklauf. Aber das funktioniert nicht, auch wenn ich es direkt in die Befehlszeile eingebe. Aber wenn ich 'screen -r' bekomme, wenn der Server läuft, dann tippe 'stop' und es wird richtig heruntergefahren.

Der Server läuft gut, wenn ich telnete und es manuell mache, muss es nur laufen, ohne von meinem entfernten Computer verbunden zu sein.

Richard Plumb
quelle
Das sieht richtig aus . Was ist der vollständige Inhalt des Skripts und wie führen Sie es aus? Produziert es irgendeine Ausgabe? Woher weißt du, dass das screennicht funktioniert hat ? Versuchen Sie, set -xam oberen Rand des Skripts (direkt nach der #!Zeile) einzufügen und die Ablaufverfolgungsausgabe zu melden, wenn Sie das Skript ausführen.
Gilles 'SO - hör auf böse zu sein'
Das ist der vollständige Inhalt des Skripts :) Der Befehl screen funktioniert, wenn ich ihn direkt
eingebe.
Sie haben geschrieben: "Wenn ich diese Zeile aus dem Skript heraus ausführe, scheint sie keinen Bildschirm einzurichten." Funktioniert der Startteil also oder nicht? Wenn nicht, siehe meinen ersten Kommentar.
Gilles 'SO - hör auf böse zu sein'
Ich versuche, es als unMENU-Benutzerskript auszuführen. Wenn ich das Benutzerskript mit genau diesem Bildschirmbefehl habe, passiert nichts. Wenn ich den Befehl screen in ein Telnet-Fenster eingebe, wird der Server auf einem Bildschirm gestartet, wie Sie es erwarten würden. Ich glaube, es gibt einen Unterschied, den ich in der Art und Weise, wie unMENU-Benutzerskripte behandelt werden, nicht verstehe.
Richard Plumb
Jetzt kommen wir voran. Bitte aktualisieren Sie Ihre Frage mit Informationen darüber, wie Sie unMENU verwenden. Und versuchen Sie , zwei Linien #!/bin/bashund set -xan der Spitze des Skripts, und zeigen uns die Trace - Ausgabe aus dem Skript. Möglicherweise müssen Sie in der unMENU-Dokumentation nachsehen, wo diese Ausgabe hingeht.
Gilles 'SO - hör auf böse zu sein'

Antworten:

40

Ich kann zumindest einen Teil des Problems lösen: Warum stopfunktioniert der Teil nicht? Experimentell wird beim Starten einer Bildschirmsitzung im getrennten Modus ( screen -d -m) kein Fenster ausgewählt, sodass später mit gesendete Eingaben screen -X stuffeinfach verloren gehen. Sie müssen explizit angeben, dass Sie die Tastenanschläge an Fenster 0 ( -p 0) senden möchten . Dies ist auf jeden Fall eine gute Idee, falls Sie in dieser Bildschirmsitzung aus irgendeinem Grund andere Fenster erstellen.

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

(Bildschirmübersetzung ^Mnach Control-M, dem von der EnterTaste gesendeten Zeichen .)

Das Problem beim Starten der Sitzung über ein Skript hängt wahrscheinlich mit unMENU zusammen.

Gilles 'SO - hör auf böse zu sein'
quelle
1
schön, funktioniert super (zumindest von der Kommandozeile aus, wird die unmenu Jungs später anstupsen). Dies scheint einige Leute geworfen zu haben und es ist das erste Mal, dass ich eine konkrete Lösung sehe. Ich wünschte nur, ich hätte genug Punkte, um dich zu wählen: D
Richard Plumb
Verdammt noch mal! Es funktioniert sogar Bildschirm ist bereits angebracht, ohne es wieder anzubringen! Was ist eine großartige Möglichkeit, Befehle von anderen Apps im System an einfache Apps zu senden. Vielen Dank! :)
Grzegorz Wierzowiecki
Ich hatte dieses Problem nie, wahrscheinlich, weil ich immer vorhatte, mehrere (benannte) Fenster in meiner Bildschirmsitzung zu haben, und ich wähle Fenster immer nach Namen.
Ekevoo
Manuell, als Referenz: -X Sendet den angegebenen Befehl an eine laufende Bildschirmsitzung. Sie können die Option -S verwenden, um die Bildschirmsitzung anzugeben, wenn mehrere Bildschirmsitzungen ausgeführt werden. Mit der Option -d oder -r können Sie festlegen, dass der Bildschirm nur nach angehängten oder getrennten Bildschirmsitzungen suchen soll. Beachten Sie, dass dieser Befehl nicht funktioniert, wenn die Sitzung kennwortgeschützt ist.
KrisWebDev
3
das klappt bei mir nicht Ich habe einen Bildschirm mit erstellt screen -d -m -S hiund dann ausgeführt screen -S hi -p 0 -X stuff "cd <some_directory>^M"und erhalte nichts als Ergebnis ... er sendet nur "cd <some_directory> ^ M" als Zeichenfolge und interpretiert "^ M" nicht als Eingabetaste ...
Tanner Strunk
23

Zunächst ein Hinweis zur einfachen Eingabe von Zeilenumbrüchen:

Nur eine $()Bemerkung , dass das Konstrukt Zeilenumbrüche aus der Ausgabe des Befehls entfernt, damit die Ausgabezeilen als Argumente für andere Programme verwendet werden können. Dies kann zu unerwartetem Verhalten führen. In diesem Fall gehe ich davon aus, dass Sie speziell versuchen, das Äquivalent von EnterTastenanschlag zu senden . Während der Wagenrücklauf, mit dem Sie senden \r, nicht gestreift wird, gibt es mehrere einfachere Möglichkeiten, dieses Zeichen einzugeben, ohne den zusätzlichen Befehl zu benötigen.

  1. Sie können in Ihre doppelten Anführungszeichen einen regulären Zeilenumbruch einfügen

    screen -S minecraft -X stuff "stop
    "
    
  2. Oder Sie geben das Zeichen mit der Ctrl+ v Enter-Sequenz in eine Terminalzeile ein . Das sieht ^Mim Terminal ungefähr so ​​aus, ist aber ein spezieller Newline-Charakter.

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

Zweitens: Ein Hinweis zum fehlerhaften Bildschirmverhalten. ( Erklärung und Lösung von Gilles )

Bildschirm hat ein Problem mit dem Akzeptieren von Eingaben in eine Bildschirmsitzung, die noch nie angehängt wurde. Wenn Sie dies ausführen, ist dies fehlgeschlagen:

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

Aber wenn Sie dies ausführen, wird es funktionieren:

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

Zum Schluss könntest du die viel besser benommenen tmuxanstatt benutzen screen.

GNU-Screen ist seit vielen Jahren ein De-facto- Terminal-Multiplexer, aber es wurde lange nicht mehr entwickelt und Fehler und Macken werden nicht behoben. Tmux befindet sich in der aktiven Entwicklung. Es enthält viele Funktionen, die der Bildschirm nicht berühren kann, und das Verhalten ist intuitiver. Außerdem ist es besser dokumentiert. So würden Sie Ihren Code konvertieren:

# 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
quelle
Wenn ich manuell mit screen -r umschalte, kann ich den Bildschirm sehen und es wird überhaupt kein Text eingegeben. Selbst wenn der Wagenrücklauf fehlschlug, sollte ich immer noch "Stopp"
eintippen
Wenn ich ein Skript mit screen -r in einer Zeile habe und dann screen -X "stop ^ M", stoppt es den Server, beklagt sich aber auch mit "error uknown option r"
richard plumb
Ich habe es hier getestet, indem ich eine Bildschirmsitzung erstellt habe und dann den obigen Befehl verwendet habe, und es funktioniert einwandfrei. Können Sie mit eine Verbindung zu Ihrer Bildschirmsitzung herstellen screen -d -RR minecraft?
Caleb
ja, das verbindet mich mit dem bildschirm. so bleibt screen -r .. hängen, wenn ich screen -s minecraft -X stuff "stop ^ M" versuche, dann manuell screen -r, gibt es 'stop' text auf dem screen.
Richard Plumb
Funktioniert bei mir. Vielleicht haben Sie etwas Ungewöhnliches in Ihrem .screenrcoder Sie haben eine Reihe von Defunkt-Screen-Sessions mit diesem Namen geöffnet, und Sie senden Daten an die falsche Adresse? screen -list?
Caleb
4

Ich entschuldige mich für das Ausgraben dieses alten Postens, aber dies hätte mir bei meinen Bemühungen geholfen, wenn diese Informationen zu dem Zeitpunkt verfügbar gewesen wären, als ich ein ähnliches Problem hatte. Es gibt viele Fragen zum Senden von Bildschirmbefehlen in einem Bash-Skript. Wie beim Katzenhäuten mag dies geschehen, aber ich mag es so. Mit diesem können Sie jeden Befehl senden oder irgendetwas sagen, indem Sie die Funktion say_this aufrufen.

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

Das ist mit 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
quelle
Schön und prägnant ... Willkommen bei U & L
eyoung100