Creating new 'screen' within existing screen - linux

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

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 do I pass a command to a screen session?

I'm writing a Linux shell script in which I need to start a new screen session, run a node.js server in the screen, then detach from the screen so that my server runs in the background.
Right now, these are the commands I run manually to do this:
screen
node server.js
[detach screen]
However, I need a way to automate this via the script, and if I just use the above commands in a shell script, it creates the screen and gets stuck there. How can I pass the "node server.js" command to the screen command?
EDIT:
Based on the suggested answer I have a script that works, except that I need to manually create a screen and detach from it before I run it. I tried adding screen -d -m as the first line to create a detached screen, but the script hangs after that line.
tempfile=$(mktemp)
indices=`tail -1 debug.log`
cat > $tempfile <<EOF
node server $indices
EOF
screen -X readbuf $tempfile
screen -X paste .
rm -f $tempfile
How can I create and detach a screen with the script?
This didn't work either:
screen
screen -d
It is as simple as this:
screen -md node server.js
This requires the command to run as a service (as it does), otherwise the screen stops immediately.
To optionally also set a name for the session (e.g. "session-name"):
screen -mdS session-name node server.js
You can then attach to the screen with:
screen -rd session-name
If you want to redirect all output to a file, you can do like this:
screen -mdS session-name bash -c 'node server.js &> output.log'
You can then monitor the output with e.g.:
tail -f output.log
You can list your running screens with:
screen -ls
or
screen -list
Example: Start a Python3 web server in a detached screen
Start a Python3 web server listening on port 8000 that serves files in the current directory, in a named
detached screen:
screen -mdS my-web-server python3 -mhttp.server
Or, with logging to a file:
screen -mdS my-web-server bash -c 'python3 -mhttp.server &> output.log'
For Python 2.x it looks like this:
screen -mdS my-web-server bash -c 'python -mSimpleHTTPServer &> output.log'
EDIT: Try this:
tempfile=$(mktemp)
cat > $tempfile <<EOF
node server.js
EOF
screen -S SessionName -X readbuf $tempfile; screen -RdS SessionName
screen -X paste .
rm -f $tempfile
It should create the temp file, create a screen called SessionName and runs the commands, then delete the temp file. Let me know if that works.

Using screen in bash script

I'm running a game server on a remote server where I use a detached screen instance to leave it running.
I'm now creating a script that can be used to shut down the server, back up all the vital files and start it up again, however I'm having a few difficulties with dealing with the screen.
I assumed that I could just switch into the detached screen in the script (after the server had already been shut down) by calling screen -r in the script.
But that doesn't seem to work because if I run the script from outside screen it just launches the server in that session.
screen -r
cd ~/servers/StarMade/
sh StarMade-dedicated-server-linux.sh
screen -d
This is what I thought would do the trick but it doesn't. Maybe somebody can help me out here. I'm not a bash expert. In fact this is propably my first bash script that doesn't include "Hello World". Thanks.
Your script, as in your example, will get executed by your sell, not the one in the screen. You need to tell the running screen to read a file and execute it - that's what the -X option is for.
Try
tempfile=$(mktemp)
cat > $tempfile <<EOF
cd ~/servers/StarMade/
sh StarMade-dedicated-server-linux.sh
EOF
screen -X readbuf $tempfile
screen -X paste .
rm -f $tempfile
You can leave screen running in a 2nd terminal session to see what happens.

Kill Attached Screen in Linux

I created a screen "myscreen" in linux and it stopped responding abruptly. I closed the terminal and tried to reopen it. "screen -ls" shows that the screen is Attached. I tried the following commands but nothing responds.
screen -r myscreen
screen -D myscreen
screen -D -RR myscreen
screen -X -S myscreen quit
Any help to reattach to the screen or to kill the screen is very much appreciated.
screen -X -S SCREENID kill
alternatively, you can use the following command
screen -S SCREENNAME -p 0 -X quit
You can view the list of the screen sessions by executing screen -ls
Create screen from Terminal:
screen -S <screen_name>
To see list of screens:
<screen -ls> or <screen -list>
To go to particular screen:
<screen -x screen_name>
<screen -r screen_name>
Inside screen
To Terminate screen:
give ctrl+d screen will get terminated
To Detach screen:
give <ctrl+ad>or <screen -d >screen will get detached
To reattach screen:
screen -x <screen_name> or screen -r <screen_name>
To kill a screen from Terminal:
<screen -X -S screen_name quit>
or
<screen -X -S screen_name kill>
You can use screen_name or process_id to execute commands.
This worked for me very well. Get the screen id via:
screen -r
or
screen -ls
then kill the screen: kill -9 <screenID>
it now becomes a dead screen,
then wipe it out with: screen -wipe
To kill a detached screen use this from the terminal:
screen -X -S "SCEEN_NAME" quit
If you are attached, then use (from the terminal and inside the screen):
exit
From Screen User's Manual ;
screen -d -r "screenName"
Reattach a session and if necessary detach it first
You could create a function to kill all existing sessions. take a look at Kill all detached screen sessions
to list all active sessions use
screen -r
when listed, select with your mouse the session you are interested in and paste it. like this
screen -r
Suppose your screen id has a pattern. Then you can use the following code to kill all the attached screen at once.
result=$(screen -ls | grep 'pattern_of_screen_id' -o)
for i in $result;
do
`screen -X -S $i quit`;
done
i usually don't name my screen instances, so this might not be useful, but did you try screen -r without the 'myscreen' part? usually for me, screen -r will show the PIDs of each screen then i can reattach with screen -d -r <PID>
You can find the process id of the attached running screen.
I found it same as the session id which you can get by command:
screen -ls
And you can use following command to kill that process:
kill [sessionId] or sudo kill [sessionId]
None of the screen commands were killing or reattaching the screen for me. Any screen command would just hang. I found another approach.
Each running screen has a file associated with it in:
/var/run/screen/S-{user_name}
The files in that folder will match the names of the screens when running the screen -list. If you delete the file, it kills the associated running screen (detached or attached).
For result find: Click Here
Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. There is a scrollback history buffer for each virtual terminal and a copy-and-paste mechanism that allows the user to move text regions between windows.

How to stop a screen process in linux?

I am running a script on a remote server. I ran the script in screen, however I need to stop it before it completes since I need to update the script. I can easily detach from screen, however, is there a way to kill a screen process?
CTRL+a and then 'k' will kill a screen session.
There are a couple of 'screen' ways to kill a specific screen session from the command line (non-interactively).
1) send a 'quit' command:
screen -X -S "sessionname" quit
2) send a Ctrl-C to a screen session running a script:
screen -X -S "sessionname" stuff "^C"
In both cases, you would need to use 'screen -ls' to find the session name of the screen session you want to kill ... if there is only one screen session running, you won't need to specify the -S "sessionname" parameter.
I used this to quit hundreds of erroneous screen sessions created by a buggy command:
for s in $(screen -ls|grep -o -P "1\d+.tty"); do screen -X -S $s quit; done;
where: the grep -o -P "1\d+.tty" is the command to get session names with Perl-like name regex "1\d+.tty" which captures all sessions start with number 1, has some other numbers (\d) and end with .tty
Warning:
You should test with this command first to see you get the exact list of sessions you want before apply the above command. This is to avoid quitting unwanted sessions:
for s in $(screen -ls|grep -o -P "1\d+.tty"); do echo $s; done;
I always to this echo test whenever the list in for loop is not clear, for example, the one generated by sub-command in $() expansion.
previous answers didn't work for me on a winputty terminal and amazon ssh server connection.. but this one does work:
screen -S yourscreentitlehere -X stuff $'\003'
references:
Sending ctrl-c to specific screen session
$'\003' is ctrl+c http://donsnotes.com/tech/charsets/ascii.html
stuff is https://www.gnu.org/software/screen/manual/screen.html#Paste
I am using putty, and it seems I am already in the screen and couldn't open and close. Every time I do "exit", I just close the putty window. Here is the termimal print
>>screen -r
21063.unlimited (11/08/20 15:45:19) (Attached)
24054.cure6 (11/08/20 09:46:13) (Attached)
There is no screen to be resumed.
and
screen -S 21063.unlimited -X stuff $'\003'
does not do anything.
I found that as simple as the following line works perfect
screen -x 21063.unlimited
it sends me back into the screen and from there "exit" works.
Note that it is lower-case -x

Resources