Shell GNU-Screen -X Stuff problems - linux

OPTIONS="java -Xms1024M -Xmx1024M -jar craftbukkit.jar"
PROCESS=server01
screen -dmS $PROCESS $OPTIONS nogui # Starting the application
screen -x $PROCESS -X stuff `printf "stop\r"` # Closing the application
screen -x $PROCESS # Attaching to the terminal of the application
The application works fine at the start, however I get problems with stuff 'printf "stop/r"'
It seems not to work when I just start up, wait some time and then try to stop it with the command above. But the strange thing is, that if I did screen -x $PROCESS and detach (ctrl-A & ctrl-D) and then I use the Stop command it does work. So is there a way around to stuff printf without screen -x $PROCESS?

Adding the argument -p 0 should fix it. Something like this:
screen -x $PROCESS -p 0 -X stuff `printf "stop\r"`
(From screen documentation: -p window Preselect the named window if it exists.)

Related

Startup script to run detachted screen, switch user, and run multiple bash commands

I want to create a small startup script that does multiple things in a row in a screen.
The script starts a named, detached screen (screen -S discordbot -d -m works)
The user inside the script is changed (Neither screen -S discordbot -X "su discordbot", screen -S discordbot -X su discordbot, nor screen -S discordbot -d -m bash -c "su discordbot;" seems to work, or at least subsqeuent commands are not executed).
A cd folder change is exectuded.
A java jar or other script is started.
As I run multiple bots, the script needs to be able to do this in slight variation multiple times in a row. Any pointers on how this could be done?
The screen session that you start up will exit as soon as the process that you started exits.
This works, for instance:
$ screen -S discordbot -d -m bash
$ screen -ls
There is a screen on:
2948.discordbot (Detached)
1 Socket in <...>
As does this:
$ screen -S discordbot -d -m bin/discordbot.sh
Where bin/discordbot.sh looks like this:
#!/bin/sh
echo "Sleeping..."
sleep 10
/bin/echo -n "Hit enter to finish this script: "
read
The last two lines to prevent the screen from exiting prematurely. The other various things you want to do within that startup script should also work, assuming that you do this as root so that the su will work without prompting.

how to create and move between screens in a bash.sh script [duplicate]

Was wondering how I can start up a command such as:
while :; do ./myCommand; done;
But instead of doing the usual
screen -S nameOfMyScreen
Then the command
while :; do ./myCommand; done;
Then detach the screen
^a ^d (Control "a" the control "d"
I would like it to start and detach. Thanks!
screen -d -m sh -c "while :; do ./myCommand; done;"
Explanation:
-d -m starts screen in detached mode (create session but don't attach to it)
sh -c commandline starts a shell which executes the given command line (necessary, since you are using the while builtin).
From screen -h, these look useful:
-dmS name Start as daemon: Screen session in detached mode.
-X Execute <cmd> as a screen command in the specified session.
I haven't done this myself, but that's where I'd start.
Update:
The top of the help also says
Use: path/to/screen [-opts] [cmd [args]]
so the -X switch may be to execute a screen command as opposed to a shell command. You might just be able to put your command after the -dmS <name> without any -X switch.

Creating new 'screen' within existing screen

I have a game server. It runs on linux via dotnet. I run this inside a 'screen' session.
However I am struggling with restarting this server.
From outside, it is easy. I just kill existing screen via name and create new one.
However when I want to restart server from inside (existing game process starts new process that runs script that kills named screen and starts new one)
To be specific:
stop.sh:
screen -r gameserver -X quit
start.sh:
screen -L -A -m -d -S gameserver /usr/bin/dotnet /gameserver/game.dll
restart.sh:
/gameserver/stop.sh
/gameserver/start.sh
Now If I run restart.sh programmatically from inside screen, it calls stop.sh, which terminates current screen and also this restart.sh script, so the new one is not started.
I tried to run restart.sh via screen:
screen -L -m -d /bin/bash -c /gameserver/restart.sh
But it still doesn't work...
I would expect this to run restart.sh in new screen, where the 'gameserver' screen will terminate and start new one and after that screen running restart.sh will stop. But no :(
Any ideas?
Cant you just kill this process inside the screen?
Something like
screen -r gameserver kill $(ps aux|grep 'game.dll'|awk '{print $2}') ?
I think you probably should NOT run such a script inside screen. Kill the whole session then re-create it inside screen is kind of weird.
And in your script stop.sh, though using -r with -X may sometime work, it doesn't make much sense. I think you should use -S instead of -r.
Run outside screen:
If you replace stop.sh with screen -S gameserver -X quit, and run restart.sh outside screen, it should work.
Run inside screen:
However, if you really need to run it inside screen, you could try to kill a window instead of terminate the whole session.
stop.sh:
# Create a new window before kill 'server'
# Without this, the session will be terminated if 'server' is the only window
screen
screen -p server -X kill
start.sh:
# Are we in the 'gameserver' session?
if [ "${STY#*.}" = gameserver ]; then
# Create a window named 'server' and run your program in it
screen -t server /usr/bin/dotnet /gameserver/game.dll
else
# Create a new screen session named 'gameserver'
# And it's default window is named 'server'
# -T $TERM to make sure things such as '-t' work
screen -L -A -m -d -S gameserver -t server -T $TERM /usr/bin/dotnet /gameserver/game.dll
fi

xterm doesn't run shell script

so I'm trying to use this command:
export DISPLAY=:1; /usr/bin/xterm -hold -e /path/to/shscript
Where shscript is:
#!/bin/bash
echo "Restarting ... $(date)" >> /var/log/mw2.txt
if screen -ls | grep -q 'test'; then
screen -X -S test quit
sleep 1000
screen -d -m -S test wine iw4m.exe -dedicated -console +dw_licensefile license.dat +set net_port "28960" +set party_maxplayers 18 +exec server.cfg +map_rotate +set fs_game "mods/tsd"
else
screen -d -m -S test wine iw4m.exe -dedicated -console +dw_licensefile license.dat +set net_port "28960" +set party_maxplayers 18 +exec server.cfg +map_rotate +set fs_game "mods/tsd"
fi
So I want to launch a new xterm window and it to run a shell script.
But whatever shell script I try to use, it doesn't run it. It just goes blank. All other commands work, but when I put a shell script in it, it just goes blank and does nothing. I can't find a solution for this, please help, thank you.
I get this with set -x:
++ date
+ echo 'Restarting ... (date)'
+ grep -q test
+ screen -ls
+ screen -d -m -S test -wine iw4m etc...
I think you get exactly what you have asked for...
From screen's man page:
-d -m Start screen in "detached" mode. This creates a new session but
doesn't attach to it. This is useful for system startup
scripts.
On the other hand you use -hold for xterm:
-hold Turn on the hold resource, i.e., xterm will not immediately
destroy its window when the shell command completes. It will
wait until you use the window manager to destroy/kill the win‐
dow, or if you use the menu entries that send a signal, e.g.,
HUP or KILL.
And that's exactly what you see. xterm starts, executes screen which runs, but you don't see the output as screen does not attach to the virtual terminal. Since screen has detached the shell script exits and xterm holds the window for you to destroy it at your leisure.
I bet that if in another xterm you attach to the session with screen -S test you'll see the output.
Yep. It was the wine command failing. I changed some stuff, and it works now. I had to put cd /home/MW2 in the script for it to be able to run the iw4m.exe, then screen -S etc.

How can I send stuff commands to a start-in-detached screen?

Any session that I start with "-d -m" doesn't accept "-X stuff [...]" commands unless I've attached to the screen at least once. There is no error message, the commands just do not get through.
The problem is that I start the session from a cron job and am unable to attach to the screen from within cron.
Steps to repeat
$ screen -m -d -S mydaemon bash
$ screen -S mydaemon -X stuff "`printf "exit\\r"`"
$ screen -ls
32456.mydaemon (Detached)
$ screen -r -S mydaemon
$ ^a d
$ screen -S mydaemon -X stuff "`printf "exit\\r"`"
$ screen -ls
No Sockets found in /var/run/screen/S-user
^a d indicates pressing Ctrl+a then pressing d.
Versions
CentOS release 5.5 (Final)
Screen version 4.00.03 (FAU) 23-Oct-06
Edit: The best answer to this question is this other SO answer. I leave my kludgey solution here, anyway, in case it inspires a solution to a similar problem.
A possible workaround is to use a second, already running and detached screen session to start the screen session to which you want to send the "stuff" command in attached mode, and then send that screen session a detach command and then the stuff command.
$ screen -dmS spawner
$ screen -S spawner -X screen screen -dR mydaemon
$ sleep 1 # may be necessary
$ screen -S mydaemon -X detach
$ screen -S mydaemon -X stuff "whatever"
(Note: the doubled "screen" is not a typo!) You are still left with an unstuffable screen session (spawner) but if the resources it takes are important you can always just use "kill -TERM ..." or its ilk to terminate it (or have it automatically exit after a certain amount of time by starting it with something like
$ screen -dmS spawner bash -c "sleep 60"
or similar).
Have you considered using tmux instead? It is much more suitable for non-interactive tasks.
Thanks for Ron Kaminsky.
I found another way to kill 'spawner' screen
$ screen -dmS spawner
$ screen -S spawner -X screen screen -dR mydaemon
$ sleep 1 # may be necessary
$ screen -S mydaemon -X detach
and add below line
$ screen -S mydaemon -X screen screen -S spawner -dR
$ sleep 1 # may be necessary
$ screen -S spawner -X detach
$ screen -S spawner -X kill
screen -d -m /bin/bash "test.sh"
screen (detached) (mobile) (shell) "What to execute"
$ screen -d -m /bin/bash "test.sh"
$ screen -li
There is a screen on:
8540..Satelite (10/17/2013 04:53:22 AM) (Detached)
1 Socket in /var/run/screen/S-matt.
Using the .screenrc file, you can set things to start;
screen -t <title> <window position> <command>
So, if you wanted to start top in window 7, you'd do
screen -t window7top 7 top

Resources