49

I'm trying to force GNU screen to create a "virtual" terminal, without attaching to it, execute script inside and NOT terminate session once script ends.

I tried many combinations, including:

screen -dmS udplistener /share/Sys/autorun/start_udp_listeners.sh

or

screen -S udplistener -X /share/Sys/autorun/start_udp_listeners.sh

and none of them worked. I either get session without executed script, script executes, but session is terminated once it finishes or I'm getting "No screen session found" error.

What I'm basically trying to do is to run UDP listener, written in PHP and make it work in infinte loop (don't break listening). Yes -- I could run PHP script with & at the end, forcing PHP CLI to run as daemon. The problem is, that I'm using a piece of junk called server (QNAP -- never, ever buy this junk!) which does seems to be ignoring this. As soon as I logoff SSH session, scripts stops.

So screen seems to be the only option. But I can't understand, why it terminates session once executed command or script ends?

EDIT: I've also tried example found in the Internet:

screen -dmS name
screen -S name -p windowname -X stuff 'mc
'

No lack! After attaching to it (screen -R name) I see that Midnight Commander HASN'T been executed. Though example author said, it will be.

trejder
  • 741
  • The way you are invoking screen, you only create one window to run a single command. When the command exits, the window closes and screen has nothing left to do, so it exits. – jw013 Sep 05 '12 at 20:39
  • So... is there a way to open two windows (using command line only, no keyboard combinations), one to execute a script and second to prevent screen from closing? BTW: I still don't get the idea behind! If I call screen -dmS name, I create a detached window, which also has nothing left to do. But it isn't automatically closed! But when I want to execute something in that detached screen, it ends once execution is done. Why? I don't see logic here. Can have window doing nothing, but can't have window doing something and then doing nothing? – trejder Sep 05 '12 at 20:45
  • 2
    When you start a window without specifying a command, it is not "doing nothing". The "something" it is doing is running an interactive shell, which does not exit until you exit it manually. – jw013 Sep 05 '12 at 20:49
  • Cool! Thanks for an explanation! So... back to the question... is there any way to run a command inside a detached screen/window and NOT to end that session, once command execution ends? Also, please take a look at updated question. Thank you. – trejder Sep 05 '12 at 21:00
  • This script is executing two UDP listeners written in PHP. Though both are executed as daemons (with & at the end), due to buggy server (QNAP), they're are terminated when session ends (I was told, they shouldn't on normal Linux, if executed with &). So I'm not looking to do anything after start_udp_listeners.sh finishes, only how to prevent session from being terminated. As long as it isn't, my PHP listeners are working just fine. – trejder Sep 05 '12 at 21:11
  • 1
    One way to see what was on the screen is to use Logfile:

    " -L tells screen to turn on automatic output logging for the windows. "

    – Antti Rytsölä Jan 13 '23 at 10:55

3 Answers3

60

To keep screen busy after the script completes, just keep something persistent running in a window. The simplest choice for that "something" is probably an interactive shell. Here's one way to do it (assuming bash as the choice of interactive shell):

screen -dmS session_name sh -c '/share/Sys/autorun/start_udp_listeners.sh; exec bash'
  • -dm: starts screen in detached mode
  • -S: sets session name for screen for easier retrieval later on
  • sh -c '...': instead of simply running your script, which will terminate, use sh -c to run multiple commands
  • exec bash: after the script terminates, the sh from above will switch over to an interactive shell (bash), which should never exit until something external terminates it. This will keep screen open as long as the bash instance is alive.
jw013
  • 51,212
  • 1
    Hm... seems you're my life saviour! :] Extending your solution with export IGNOREEOF=1 to prevent accidential termination with Ctrl+D should give me the perfect solution, I've been looking whole long evening. THANKS! :] – trejder Sep 05 '12 at 21:34
  • This doesn't work on Debian as of today, -c is an argument to read an alternative .screenrc file... – ToVine Jan 31 '15 at 22:44
  • @ToVine works perfectly on Debian Stable (Wheezy). I used bash -c though. – Neurotransmitter Apr 09 '15 at 09:42
  • @TranslucentCloud did you enclose the whole command "bash -c ..." in quotes? The last time I tried it (right before writing the comment) it didn't work for me, not quite sure why... – ToVine Apr 14 '15 at 14:12
  • @ToVine here is my whole command: screen -LS sauf bash -c "sudo aptitude update && sudo aptitude full-upgrade; exec bash" – Neurotransmitter Apr 14 '15 at 16:24
  • Thanks! In Arch Linux with an Anaconda Python 3.5 virtual environment ("py35") established, this line in my ~/.screenrc file starts a persistent window named Py3 running that Python 3.5 venv:

    screen -t Py3 bash -c "source activate py35 && python; exec bash"

    – Victoria Stuart Apr 19 '18 at 19:46
  • but we loose the stdout and the command history(to run it manually using up arrow)... looking at the window, it's like the command has never been launched in this window. Why can't we get the same behavior as manually creating a window with Ctrl-a c?! – None Jan 22 '22 at 04:26
2

I had no luck with sh -c on my raspberry pi 2 running Debian 7.8. But bash -c did the job:

Command:

/usr/bin/screen -dmS test-screen bash -c "/usr/bin/top; exec bash"
sam
  • 22,765
scotty86
  • 139
  • Could this be, because you're using (on Raspberry Pi) a different shell? The bash and sh seems to be two different shells. That's all, I think, but I may be wrong, since I'm newbie to Linux at all. – trejder Jan 14 '16 at 07:30
  • 1
    sh is the default unix-shell, it is included in raspbian (debian). The command sh also works, but not sh -c in combination with screen. – scotty86 Jan 20 '16 at 01:50
  • Thank you @scotty86, I observed the same in Linux Mint 19 (Ubuntu 18.04) and changing sh -c to bash -c did the trick. I don't understand why, both sh and bash are installed, so I'm still losing sleep over it, but at least it works. – Redsandro Oct 24 '18 at 10:56
  • sh probably points to /bin/dash instead of /bin/bash. Debian switched the default shell from bash to dash a few years ago. – scai Mar 12 '19 at 14:41
2

My motivation not terminating the session was to not loose the outputs of the session. In this context the linux tool script came to my mind.

rm script_session.log
script -e -f -a script_session.log -c "screen /dev/ttyUSB0 115200"

If the serial USB adapter is unplugged the session is terminated but I still can read the output from script_session.log. However not with cat since the escape sequences contained in 'script_session.log' make the output disappear from the terminal. You can use e.g gedit or vi or a tool that strips escape sequences from a file.

Maybe script could be useful also for detached screen session.

mashuptwice
  • 1,383
grenix
  • 121