I have made a bash file which launches another bash file in a detached screen with a unique name, I need to ensure that only one instance of that internal bash file is running at any one point in time. To do this, I want to make the parent bash file check to see if the screen by that name exists before attempting to create it. Is there a method to do this?
问题:
回答1:
You can grep the output of screen -list
for the name of the session you are checking for:
if ! screen -list | grep -q "myscreen"; then
# run bash script
fi
回答2:
You can query the screen 'select' command for a particular session; the shell result is '0' if the session exists, and '1' if the named screen session is not found:
$ screen -S Tomcat $ screen -S Tomcat -Q select . ; echo $? 0
versus:
$ screen -S Jetty -Q select . ; echo $? No screen session found. 1
Note that the '.'
after the select
is optional, but may be more robust.
回答3:
Given I can't comment I am posting this as a new answer. troyfolger's answer is a good idea and basically amounts to try and send the session a command that will do very little. One issue is that for some (older) versions of screen -Q isn't supported and so for those versions the correct command is
screen -S Jetty -X select . ; echo $?
Which send the command "select ." to the screen session called "Jetty".
Select changes which window is active and . means the current active window so this means try and change the active window to the currently active window. This can only fail if there isn't a session to connect to which is what we wanted.
If you read the info docs than it does suggest that the only use of select . is with -X as a test or to make sure something is selected.
回答4:
All the solutions proposed don't deal with screen names that don't have unique patterns, e.g. "TEST" and "TEST123". When you screen -S "TEST"
or screen -list "TEST"
, you may find yourself selecting the screen "TEST123"! There is something wrong (non-deterministic) in how GNU screen implements screen name matching.
Below is a bash function that tries to do exact matches, and return the PID.SCREEN NAME
along with an exit code:
function find_screen {
if screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 -q >/dev/null; then
screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 2>/dev/null
return 0
else
echo "$1"
return 1
fi
}
Usage - select a screen:
target_screen=$(find_screen "SCREEN NAME")
screen -S "$target_screen" ...etc...
Usage - test if a screen exists:
if find_screen "SCREEN NAME" >/dev/null; then
echo "Found!"
fi
Anyway, this will cover 99,9% cases. To be 99,99% sure, escape grep special chars in the screen name. A perfect match would require grep to match the whole line until $, including the date in parenthesis that may evolve with versions. The other perfect match method would be:
ls -A -1 /var/run/screen/S-${USER} | grep "^[0-9]*\.SCREEN NAME$"
But that's hacky, and we need to be sure that screen implementation uses this folder. I don't recommend this last method.
回答5:
%100 Work.
screen -list | grep "SESSİON NAME" && echo "Active Program" || echo "Passive Program"
回答6:
a simpler method is :
screen -xR -S SessionName
copied from a Stéphane Chazelas comment from here:
I generally use -xR to attach or create if there's nothing to attach.
so like that you do not have to search if the session name already exist, this method will attach to the session if it exist and if not then it will creat it.