14

I've been searching to find a way to send a command to a detached screen session. So far, so good. This is what I've come up with:

$ screen -S test -p 0 -X stuff 'command\n'

This command works as it should. But, I would like the output from it too, echoed straight in front of my eyes (no need for a .log file or something, I just want the output).

Using the screen -L command, is not an option.

1
  • Why does it have to be screen? Isn't this what child processes are made for?
    – Anko
    Jan 21, 2014 at 11:03

3 Answers 3

11

Use a first in first out pipe:

mkfifo /tmp/test

Use a redirect operator. Redirect command's output to /tmp/test for example like this:

screen -S test -p 0 -X stuff 'command >/tmp/test\n'

Then in another shell

tail -f /tmp/test.

Note you may also want to redirect error messages using the 2>&1 operator.

Example

As requested in the comments, let's assume we have a php script accepting user input and printing the server load on the input of "status":

# cat test.php
<?php
  $fp=fopen("php://stdin","r");
  while($line=stream_get_line($fp,65535,"\n")) 
  {
    if ($line=="status") {echo "load is stub";} 
  } 
  fclose($fp);
?>

You create two fifos:

 # mkfifo /tmp/fifoin /tmp/fifoout

You call a screen:

screen

In another console, let's call it console 2 you find out the name of your screen:

# screen -ls
There is a screen on:
        8023.pts-3.tweedleburg  (Attached)
1 Socket in /var/run/screens/S-root.

In console 2 you send the command to the screen:

 # screen -S 8023.pts-3.tweedleburg -p 0 -X stuff 'php test.php </tmp/fifoin >/tmp/fifoout\n'

you see the command appearing in the screen. Now in console 2 you can send commands to your php process:

echo "status" >/tmp/fifoin

and read from it:

# cat /tmp/fifoout
load is stub
4
  • 1
    Sorry, but this doesn't work. If I'm sending a command to the creen like 'command >/tmp/test' the process must support the >/tmp/test syntax... And it doesn't.
    – Robin
    Jan 31, 2014 at 18:46
  • For me it works, please note that I put "test" as your screen's name. You can find out your screen's name with the command screen -ls. Also, "command" should be replaced by your actual command, I tested with the command ls. Also, I tested with the bash shell. Jan 31, 2014 at 19:20
  • I know that. And it doesn't work. For example, start a PHP script in a screen window, which, for example, responds to a command "status", which returns current server load for example. That's what I'm trying to do.
    – Robin
    Feb 1, 2014 at 18:27
  • then you will need bidirectional pipes, I am adding this to my answer Feb 1, 2014 at 20:14
6

I have a python script that keeps track of numerous detached screen sessions and captures output from each (when utilization commands like free, top -bn2, iostat are periodically sent via 'stuff').

Instead of redirecting to a file and, thus, managing at least one file per detached screen session... I simply redirect to whatever tty/pts my parent session is using.

Step #1: Start a new screen session (with a human readable name) in detached-mode.

$ screen -dmS chad 

Step #2: Send your commands (I'll use the 'free -g' command along with 'uname -r') via stuff. It is important to specify the window that you want to use (in our case, the first and only window) with -p.

$ screen -r chad -p0 -X stuff "free -g; uname -r" 

Step #3: The above step only sends the command text. We need to also send a carriage return to this detached screen session to have the shell execute our command. The ASCII character 015 is a carriage return on most *nix systems.

$ screen -r chad -p0 -X eval "stuff \015"

Step #4: Redirect the output of our detached screen session to our current tty/pts:

$ screen -r chad -p0 -X hardcopy $(tty)

The output of Step #4 will look something like this:

$ free -g; uname -r
             total       used       free     shared    buffers     cached
Mem:             7          1          6          0          0          0
-/+ buffers/cache:          0          7
Swap:            1          0          1
2.6.32-358.el6.x86_64

Although this seems a bit involved, the process is easily scriptable. With python, I can parse the output of Step #4 and capture only the data that I care about.

Choosing a simple scenario like grabbing IP details, I wrote an example script to demonstrate the concepts above. Feel free to replace and tinker as you see fit.

Example python script to get IP details from a detached screen session:

#!/usr/bin/python

import pexpect, time

#spawn a new bash session
session = pexpect.spawn('/bin/bash')
#send screen commands
session.sendline('screen -dmS netIP')
session.sendline('screen -r netIP -p0 -X stuff "ifconfig eth0 | grep -v eth0 | head -1"')
session.sendline('screen -r netIP -p0 -X eval "stuff \\015"')
#give the command a chance to execute before reading the output of our detached screen
time.sleep(0.1)

#use the output of the uname command as our string to expect
session.sendline('screen -r netIP -p0 -X hardcopy $(tty); $(uname)')
session.expect('Linux')

#parse the output - only concerned with the 'inet' line
output = session.before.split('\n')
for o in output:
    if 'inet' in o:
        print o

#kill the screen
session.sendline('screen -r netIP -p0 -X quit')
time.sleep(0.1)

session.close()

Above script in action:

$ python screen-output-test.py 
      inet addr:192.168.1.201  Bcast:192.168.1.255  Mask:255.255.255.0
2
  • I like this answer a lot better than the accepted one, because it doesn't rely on the screen being in "shell prompt" state, but works with whatever is running in that screen as well. Feb 25, 2019 at 16:05
  • However, it requrires the output to fit on the screen. I found screen -X logfile /tmp/something; screen -X log on; screen -X stuff "command param"; screen -X log off to work even better in that scenario. Feb 25, 2019 at 16:12
-1
screen -S myscreen

screen -R myscreen -X exec command

Example:

screen -R myscreen -X exec top

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .