Reputation: 2842
I would like to start screen
sessions in a detached state so that they terminate once the script finishes and so that I can write a script to execute multiple screen
sessions without me having to manually, one by one, start each session and then detach, before moving onto to the next screen session.
This script depends on certain environment variables being set. Normally, when I run this script outside of screen
, in a regular bash
shell, I simply have these environment variables set in my .bash_profile
file.
Furthermore, when I start screen in a non-detached state and put in my .screenrc
file:
shell -$SHELL
then I also have no problems.
The issue only arises when I perform screen -dm
then my script fails to run as the environment I need is not set.
How can I tell screen to refer to the .screenrc
file when starting in a detached state such that it ultimately sources my .bash_profile
on startup?
UPDATE
When I perform screen -dmL env
I can see that some but not all of my environment variables are present.
Upvotes: 5
Views: 3602
Reputation: 127
No need for ~/.screenrc
Make your ~/.bash_profile one line: source ~/.bashrc
Put your aliases and environemnt variables in ~/.bashrc
In ~/.bashrc, write code like this:
alias myalias="echo ThisWorks"
run_myalias_in_bg_screen (){
screen -dmS mytestscreen bash -c 'exec bash'
screen -r mytestscreen -p0 -X stuff "myalias"
screen -r mytestscreen -p0 -X eval "stuff \015"
}
Now test it out in your terminal
$ run_myalias_in_bg_screen
$ screen -r mytestscreen
Upvotes: 2
Reputation: 11922
I believe your problem is that when starting screen
in detached mode, screen
does not start a login shell or an interactive shell, and so your .bash_profile
is not sourced (see the "INVOCATION" section of man bash
for an explanation of what files are sourced when on start up). Note that the leading -
in your
shell -$SHELL
setting means the shell will always be started as a login shell, and so .bash_profile
will be sourced.
Some possible solutions to your problem:
don't start screen
in detached state. Note that screen
terminates when the script finishes when started in the usual way, if the script is given as a command. E.g., for the script test.sh
:
#!/bin/bash
for n in `seq 1 5`; do
echo $n
sleep 1
done
doing screen ./test.sh
runs the script and terminates after 5 seconds.
manually source your .bash_profile
in the script you're running in screen. I.e. add
source ~/.bash_profile
to the beginning of your script, MyScript
.
I still suspect the problem is that your .bash_profile
is not being loaded, so let's be sure your .screenrc
is being loaded. Try adding
screen touch /tmp/when-was-screen-rc-sourced
to the end of your ~/.screenrc
and then do
screen MyScript
and then
ls -lt --full-time /tmp
Try starting screen a few different ways and see if ~/.screenrc
is really failing to load.
Similarly, you can add a line
touch /tmp/when-was-bash-profile-sourced
to the end of your ~/.bash_profile
to see when that is loaded.
Here is an example that shows that screen
does run your script when you have the line
screen touch /tmp/when-was-screen-rc-sourced
at the end of your ~/.screenrc
.
Here is the test file test.sh
:
#!/bin/bash
touch /tmp/when-did-test-sh-start
for n in `seq 1 5`; do
echo $n
sleep 1
done
touch /tmp/when-did-test-sh-finish
Here is the evidence. Running
$ touch /tmp/when-did-we-start; screen -d -m ./test.sh; sleep 6; ls -ltr --full-time /tmp | tail -n4
gives output
-rw------- 1 collins collins 0 2013-11-06 14:43:03.643564802 -0800 when-did-we-start
-rw------- 1 collins collins 0 2013-11-06 14:43:03.659565385 -0800 when-was-screen-rc-sourced
-rw------- 1 collins collins 0 2013-11-06 14:43:03.671565892 -0800 when-did-test-sh-start
-rw------- 1 collins collins 0 2013-11-06 14:43:08.707770194 -0800 when-did-test-sh-finish
So, I still think the problem is related to your ~/.bash_profile
(or
whatever defines your missing env vars) not being loaded.
At this point it might be easier to understand exactly what you're
trying to accomplish, and then come up with a better way to do it. To
do this it would be helpful for you to provide a minimal example
script that illustrates your problem (i.e. it works when you run it
directly, or manually after starting screen, but not when run directly
via screen ./example.sh
or screen -d -m ./example.sh
).
But, in the mean time, here's another potential workaround (did you
ever try my second original suggestion above, of just sourcing your
~/.bash_profile
in your script directly?):
Run your script with bash, explicitly making bash interactive and/or a login shell. E.g. for an interactive login shell do
screen -d -m bash -i -I ./MyScript
See
here
for a nice summary of what files bash loads in what modes. According
to man bash
, the bash -i -I
combination should make bash run your
script in interactive login mode, and hence ~/.bash_profile
should
get sourced.
Upvotes: 3