5

How can i create a screen in detached mode only if it doesn't exist?

This creates a screen named name in detached mode but will create duplicates

screen -dmS name command

This creates a screen only if it doesn't exist but not detached

screen -dRms name command

How do i combine both? I need to create multiple screens in a batch file so reattaching is not convenient. I want to use the batch file to "restart" screens that have died for various reasons but leave the already running ones intact.

Maciej Swic
  • 290
  • 5
  • 19

3 Answers3

1

I've just stumbled over this issue and solved it like this:

  1. Create a Python script which checks if a screen session exists.
  2. Some shell scripting

In my case, the screen session name I'm interested in is 'activity' (for my activity tracker project).

Python Script does_screen_session_exist.py

Python 3.4+; no dependencies:

#!/usr/bin/env python

"""
Check if a screen session exists.

If it does, give exit code 0.
If it doesn't, give exit code 1.
"""

import subprocess
import sys
from argparse import ArgumentParser
from typing import List

parser = ArgumentParser()
parser.add_argument("session_name")


def main(session_name: str) -> None:
    session_names = get_active_screen_sessions()
    if session_name in session_names:
        print(f"Screen session '{session_name}' exists")
        sys.exit(0)
    else:
        print(f"Screen session '{session_name}' does NOT exist")
        sys.exit(1)


def get_active_screen_sessions() -> List[str]:
    result = subprocess.run(["screen", "-ls"], stdout=subprocess.PIPE)
    output = result.stdout.decode("utf-8")
    if "No Sockets found" in output:
        return []
    assert "There is a screen on" in output

    # get lines
    lines = []
    for line in output.splitlines():
        if line.startswith("\t"):
            lines.append(line)

    # get session names
    session_names = []
    for line in lines:
        line = line.strip()
        line = line.split("\t")[0]
        line = line.split(".")[1]
        session_names.append(line)
    return session_names


if __name__ == "__main__":
    args = parser.parse_args()
    main(args.session_name)

Bash script

python does_screen_session_exist.py activity
status=$?
if [ $status = 0 ]
then
    echo 'activity' screen exists
else
    echo Start activity screen
    screen -S activity -U -d -m activity_tracker log-activity
fi
Martin Thoma
  • 277
  • 4
  • 13
0

The easiest one-line solution is to use flock with screen:

try this:

screen -S session-name -d -m flock -n /tmp/some_lockfile sleep 100
screen -S session-name -d -m flock -n /tmp/some_lockfile sleep 100
screen -ls

it will list only one session. Hope it would help.

0

Thank you for your solution. More compact python function, if someone needs it:

async def check_screen_exists(screen_name: str):
    proc = await asyncio.create_subprocess_shell("screen -ls", stdout=asyncio.subprocess.PIPE)
    stdout,stderr = await proc.communicate()
    existed_screens = [line.split(".")[1].split("\t")[0].rstrip() for line in stdout.decode("utf-8").splitlines() if line.startswith("\t")]
    if screen_name in existed_screens:
        return True