38

I am working on automating a maintenance routine that involves starting and stopping a script that is running in a screen session. My approach is to kill the screen session, and then restart it and run the command from within a script using the abilities to both create a screen and pass a command without needing to attach to the screen.

However, I am having difficulties with this. I can create the screen correctly without it attaching using screen -d -m -S screen_name. However, if I run a command based on:

screen -S screen_name-X stuff "command 1"'echo -ne '\015''"command 2"'echo -ne '\015''

with the echo -ne '\015' being wrapped with backticks rather than single quotes. It is to simulate the user pressing the enter key as the commands I use are moving to a directory and executing a script located there. This command works, but only if the screen has been attached to once it has been created. As I am trying to automate the process of creating the screen and running the commands within it I would like to avoid having to attach and detach within a script. I will be trying the suggestion of creating a shell script containing the commands I need to execute within the screen and edit according to my results.

Is there a way to create a screen and run a command within the screen either in one command, or without having to attach to the screen after creating but before execution of the command?

Thanks in advance.

**Update - having tried the suggestion to place the commands I need to execute within a shell script I have been able to successfully create a screen and execute the commands from within the screen, but I am getting the behaviour that when the script stops running the screen closes as well. This shouldnt be a problem as the script is a logging script that should only stop with the knowledge of the sys admin or through the script I am trying to develop, however it would be preferable to have the screen setup in such a way that the screen does not disappear if the script is stopped. Is it possible to achieve this behaviour? **

coffeecoder
  • 483
  • 1
  • 4
  • 8
  • 1
    I ran into this same problem and found a solution on superuser.com for anyone else who stumbles upon this problem http://superuser.com/questions/342463/gnu-screen-cant-stuff-commands-unless-the-screen-is-attached – Dan Herbert Jul 07 '12 at 01:50
  • To keep the screen open you could use something like: screen bash -c 'echo "test"; /bin/bash' – gwyn Nov 28 '12 at 17:30
  • 1
    For your auto-closing issue, you could use a special `.screenrc` that contains the line `zombie kr`, which will keep a finished window open, and you can press `k` to close the winodw, or `r` to run the command in the window again. I have this for my default .screenrc. – Martin C. Jul 11 '14 at 08:56

6 Answers6

24

I think you may be running into several issues.

If the command finishes before you re-attach, the screen will go away. You can demo this by using:

screen -d -m ls -l

It will run the ls -l command, but screen -list won't show it as the screen process has ended.

I also have no idea what you are trying to do with this \015 stuff. Perhaps updating your question would help, as what I think you're trying to do is run multiple commands in a screen session. This should be as simple as:

screen -d -m bash -c "command1 ; command2 ; command3"

If these are used a lot, perhaps you should make a shell script that runs just these commands, then use a more simple:

screen -d -m /path/to/script.sh
Anubioz
  • 3,677
  • 18
  • 23
Michael Graff
  • 6,668
  • 1
  • 24
  • 36
  • is there a way to get similar behavior without the screen detaching immediately? Say I want to start an ssh session and then detach right after; `screen -d -m ssh` will detach at the password prompt before the session is made. – bright-star Dec 23 '13 at 07:06
  • This doesn't work for me. Replacing hte "commandN" with several long-running programs results in nothing showing up in `screen -list`. Also, this doesn't name the screen as the OP is trying to do. – Cerin Sep 27 '14 at 03:07
  • I was looking to run a python program using this method. I tried to create a sh script to run it, but did not see the screen in the list. Instead I used `screen -d -m python EventGenerator.py`, which worked great – Dan Ciborowski - MSFT Nov 27 '15 at 20:36
  • 1
    That should probably be `bash -c "commands"` instead of `bash "commands"` – marcovtwout Nov 02 '16 at 08:04
  • You're right, there has to be -c . – Xdg Nov 19 '16 at 07:00
  • Would be nice to hear the flags mean? – Karl Morrison Mar 13 '18 at 14:59
  • but how to leave the screen open after the command has finished? – Nathan B Feb 15 '19 at 08:27
21

Start a detached screen

screen -dmS <screen name>

Execute command in previously created detached screen

screen -S <screen name> -X stuff '<CMD>\n'

Yes you need to type the enter symbol to submit the command or else it will just add the string to the screen.

http://osdir.com/ml/gnu.screen/2003-09/msg00029.html

Bruno
  • 103
  • 4
Yogesh
  • 219
  • 2
  • 2
  • 1
    what is 'stuff' ? – Nathan B Feb 15 '19 at 08:28
  • 2
    `stuff` is actually a command that copy-pastes another command into a screen session: stuff [string] Stuff the string string in the input buffer of the current window. This is like the "paste" command but with much less overhead. Without a parameter, screen will prompt for a string to stuff. You cannot paste large buffers with the "stuff" command. It is most useful for key bindings. See also "bindkey". [cited from https://theterminallife.com/sending-commands-into-a-screen-session/] – alisa Nov 07 '19 at 22:42
4

This did the job for me, without -c wasn't working

screen -d -m bash -c "command1; command2; command3"

Mazilu88
  • 41
  • 2
2

I've encountered this problem before, it was a bug with the cygwin implementation.

What I did was create a ".screenrc_detaching" having only the following command

#detach
detach 

and then start screen with

screen -c ~/loginScripts/tempScreenrc/.screenrc_detaching

Then you have your screen session and its already been attached and detached and you're good to pump commands to it.

Nakilon
  • 128
  • 1
  • 1
  • 8
PiersyP
  • 129
  • 2
1

A copy'n'paste way to test previous answers is:

 # No sessions:
screen -ls

 # Returns immediately:
time screen -dmS screen_descritive_session_name  bash -c 'sleep 20; hostname >> /tmp/h'

 # New session present:
screen -ls

 # File with return of command was created :)
sleep 20; cat /tmp/h

The expect result should be similar to:

No Sockets found in /var/run/screen/S-yourusernamehere.

(That means no screen-session was previously created)

real    0m0.002s
user    0m0.000s
sys     0m0.000s

(It's the time spent to create screen and detach from it. Almost instantaneous.)

There is a screen on:
    20318.screen_descritive_session_name    (20/08/2018 16:29:35)   (Detached)
1 Socket in /var/run/screen/S-yourusernamehere.

(This output show screen sessions available. Created on last command.)

sleep 20; cat /tmp/h

(This cat shows the hostname executed inside gnu-screen)

1
screen -S test -d -m -- sh -c 'ls; exec $SHELL'
Nathan B
  • 111
  • 3