sending text input to a detached screen
I can solve at least part of the problem: why the stop
part isn't working. Experimentally, when you start a Screen session in detached mode (screen -d -m
), no window is selected, so input later sent with screen -X stuff
is just lost. You need to explicitly specify that you want to send the keystrokes to window 0 (-p 0
). This is a good idea anyway, in case you happen to create other windows in that Screen session for whatever reason.
screen -S minecraft -p 0 -X stuff "stop^M"
(Screen translate ^M
to control-M which is the character sent by the Enter key.)
The problem with starting the session from a script is likely related to unMENU.
First, a note on easily entering newlines:
Just a heads up that the $()
construct strips newlines from the output of command so that the output lines can be used as the arguments for other programs. This can cause unexpected behavior. In this case I assume you are specifically trying to send the equivalent of Enter keystroke. While the carriage return you are sending with \r
won't get striped, there are several easier ways to enter that character without the need for the extra command.
You can place a regular newline inside your double quotes
screen -S minecraft -X stuff "stop "
Or you can enter the character in a terminal line using the Ctrl+v Enter sequence. This will look something like
^M
in the terminal, but it's a special newline character.screen -S minecraft -X stuff "stop^M"
Secondly, A note on erratic screen behavior. (Explanation and solution by Gilles)
Screen has an issue with accepting input to a screen session that has never been attached. If you run this it will have failed:
screen -d -m -S minecraft zsh
screen -S minecraft -X stuff "stop^M"
screen -r minecraft
But if you run this it will work:
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
Lastly, you could use the much better behaved tmux
instead of screen
.
GNU-Screen has been a de-facto terminal multiplexer for many years, but it has long ceased to be developed and bugs and quirks aren't getting fixed. Tmux is under active development, includes many features that screen can't touch, and its behavior out of the box is rather more intuitive. Also, it's better documented. Here's how you would convert your code:
# 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"
I apologize for digging up this old post, but this would have helped me in my endeavors had this information been available at the time I had a similar issue. There are many questions about how to send screen commands in a bash script. As with cat skinning this may be done, but I like this way. With this you can send any command or say anything just by calling the say_this function.
#!/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"
...
This is with 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!"