Run (GNU) Screen from script

gnu-screen

I would like to launch some application inside screen session but from a script.
Without script I would just launch screen, then open N windows with crtl-a-c and execute programs in each windows.

I tried the following

screen -d -m -S test
screen -S test -X exec tail -f /var/log/messages
screen -S test -X screen
screen -S test -X exec tail -f /var/log/xinetd.log

But when I attach the session tail is not running. If I attach the session just after screen -d -m -S startup and run screen -S startup -X exec tail -f /var/log/messages from another terminal it works.

Did I miss something ?

Edit after AlexD answer:

An half working solution is

screen -d -m -S test tail -f /var/log/messages
screen -S test -X screen tail -f /var/log/xinetd.log

Chaining screen command (the one after -X) with the command is working while exec is not probably because exec expect a current window to be defined while there is no current one when screen is detached. Thanks to AlexD for this tips.

But there is a weird side effect : when the program stop (if you attach the screen session and crtl-c the tail, or kill tail) the screen window will close.
So the behavior is not the same as Crtl-A c and run the command
Another side effect is that you can't chain 2 commands

Best Answer

The screen -S test -X screen command command is what you need to add windows to your daemon session, but not for the reasons you give. It works because -X takes a screen command and not a shell command, and the screen command to create a window is called, confusingly, screen. There is no exec screen command. There is no chaining either, unless you build your command using shell scripting (like this: screen -S script -X screen sh -c 'command1; command2;').

Calling screen -S test -X screen with no command is useless because the default command is a shell, and once you have spawned a shell, you don't have a noninteractive (and non-devious) way to run commands inside that shell. It is better to run the command by itself, without an interactive shell. A side effect is that when the command exits, the screen window doesn't have a child any more, and will close.

Now, you can ask screen to hold the window open anyway, after the command has quit. Use the zombie screen command to enable that. Your sequence looks like:

screen -d -m -S script
screen -S script -X zombie qr
screen -S script -X screen tail -f /var/log/messages
screen -S script -X screen tail -f /var/log/xinetd.log

To reattach interactively:

screen -S script -r

And finally, you can rewrite these -X commands as a screenrc script instead.

Screenrc:

zombie qr
screen tail -f /var/log/messages
screen tail -f /var/log/xinetd.log

Script:

screen -d -m -S script -c screenrc