No. The screen -X stuff
command will return immediately, because it is not aware that it is being asked to run a command in the first place, even more so when that command is complete – all it's doing is injecting keypresses (which is why you had to add the ^M
manually). As soon as the fake tty input has been sent, the command returns and your script continues.
In general, as a terminal emulator, screen does not know what exactly is happening in any specific terminal window – there's nothing that would delimit a shell prompt (or any other interactive console prompt) from regular output.
(This is not fundamentally impossible – some terminal emulators allow the shell to output "output start/end" and "prompt start/end" markers, e.g. VSCode will inject special configuration into Bash to achieve exactly that – but it requires support from the terminal emulator and cooperation from every program that would show an input prompt, and neither Screen nor Minecraft will do that currently.)
On the other hand, your script might have an easier time because it only deals with a single program, which means it only needs to wait for a specific prompt to appear, not just any prompt in general. You could implement this by having a loop that would query Screen for the current buffer "contents" using -X hardcopy
, and if the last line of that buffer is not the Minecraft prompt yet, sleep 1 second and repeat.
This is similar to how the expect
program works: one can write an Expect script to automate various kinds of interactive input, but the core of such a script is always a set of expect "this"
and expect "that"
, i.e. knowing up-front that some specific text is a "prompt" and waiting for that text.
[...]
expect "Password:" { send "$password\r" }
expect ">" { send "enable\r" }
expect "Password:" { send "$enablepwd\r" }
expect "#" { send "show run\r" }
What other Minecraft-management scripts do (such as this project, which recently switched from Screen to tmux) appears to be 1) blindly submit both "save-all" and "stop" at once, 2) wait for the server to process bot commands until it exits by itself. That is, instead of waiting for the command to complete, they wait for the result of that command.
Similarly, if you want to wait for the save to finish, you don't need to wait for the "save-all" command – you can instead use inotifywait
to wait until the server has finished writing a specific file. This can be somewhat tricky to do right (normally you'd need to use "coproc" to start inotifywait before issuing the command so that you wouldn't miss the event), but as a save is likely to take a while, it's probably fine to just do it after.
echo "waiting..."
inotifywait -q -e close_write /path/to/game
echo "probably done!"
Some programs deliberately create a specific file last, so that other tools could wait for it to appear:
echo "waiting..."
until [ -e /path/to/marker_file ]; do sleep 1; done
echo "marker file showed up"