5

Running a command in a screen and detaching is quite simple.

screen -S test -d -m echo "output of command that runs forever"

However I would also like to pipe all the output to a file for logging, how can run the following in a screen and detach.

echo "output of command that runs forever" &> output.log

Edit:

Just to clarify, I need this for a script so simple starting a screen and doing running the command and detaching is not an option.

Lesmana
  • 27,439

3 Answers3

6

You can wrap your command in an extra bash (or your actual shell) call and make redirection there:

$ screen -dm bash -c 'echo hello > ./out'
$ cat ./out
hello

From the man screen:

-d -m Start screen in "detached" mode. This creates a new session but doesn't attach to it. This is useful for system startup scripts.

Naming a session

It may be suitable to name your background jobs to disambiguate them in the screen -ls and to attach if neccessary:

$ screen -S mysession -dm sleep 20
$ screen -ls
8431.mysession  (10/04/2021 12:47:58 PM)    (Detached)

attach

$ screen -r mysession

How to pass arguments

Parameterization may be a hassle though. The arguments being passed are fed into bash starting with $0 -- note the ignore_me_arg:

# note the outer-most quotes to be single -- we don't want them to
# be expanded on the caller's side, but on the callee's one

$ screen -dm bash -c 'echo $1 > ./out' ignore_me_arg hello $ cat ./out hello

As a final example, let's say you have a program super_script that does some stuff and prints all its arguments to stdout (as echo would do). You want to call it inside screen, make a redirection, and do all that jazz with different sets of arguments. Then this should do:

$ screen -dm bash -c 'super_script "$@"  > ./out.1' arg0 arg1
$ screen -dm bash -c 'super_script "$@"  > ./out.2' arg0 arg1 arg2
... wait for screen's to finish
$ cat out.1
arg1
$ cat out.2
arg1
arg2
DimG
  • 191
4

screen -dmS workspace; screen -S workspace -X stuff $'ps aux > output-x\n'

I first create a detached session with the -d switch, I called my session workspace. I then send my command to the same session with -X stuff, I am using $'', but you could also use double quotes, but have to do a control M instead of a \n, which I don't like so I normally use the method I described above.

After this piece of code runs, you will find the output-x with the list of processes, and also if you do a:

screen -ls

you will see the session has been detached.

Since you said you are going to be running a script. You might want to have your script search for a detached session (I am using workspace), and if it exists send commands to that pre-existing session, instead of making a new session every time "screen -dmS sessionName" is ran, example is below:

    #!/bin/bash
    if ! ( screen -ls | grep workspace > /dev/null); then
       screen -dmS workspace;
    fi
    screen -S workspace -X stuff $'ps aux > output-x\n'
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
NiteRain
  • 308
  • Thank you very much, this helped. On slower vms I did have to add a sleep between the two commands for it to work reliably. – Fabian Barkhau Jan 29 '16 at 15:15
  • does this work if we wanted to monitor serial port, for e.g. screen /dev/ttyUSB0? – deostroll Jul 28 '19 at 02:36
  • Which purpose of the stuff in the command? I tried to execute the command exactly and nothing happened. No log file was created and when I activated workspace there was no any output there. I tried it in macOS's Terminal. – dmitry1100 Apr 21 '20 at 07:37
  • @C0DEF52 it is an input buffer of a window. You can search for that term in the manual page located here. Were you running the script? Or were you just running that one line. That one line connects to a screen session called workspace, and then stuffs a string as input to that window like you typed it, when you do a screen -ls you should see the session called workspace, and when you attach to that window you will see the input was indeed sent to a window, and there should be an output-x file created with the process list in it. – NiteRain Apr 21 '20 at 12:33
  • @NiteRain I tried one line and script in default macOS Terminal app. Here I recorded a video how I tried a single line variant: https://youtu.be/gpQHP3fZ8T4 – dmitry1100 Apr 22 '20 at 23:39
  • @NiteRain actually I solved my problem inside the script which std out and err I wanted to mirror. I added exec > >(tee -i logfile.log) and exec 2>&1 into it. – dmitry1100 Apr 22 '20 at 23:55
-1

You can use the disown or nohup

usage: How to monitor WGET download progress after closing SSH session

Ijaz Ahmad
  • 7,202