分离模式下的启动屏幕不会提供环境

时间:2013-11-05 21:30:55

标签: bash shell environment-variables gnu-screen

我想以分离状态启动screen个会话,以便在脚本完成后终止它们,以便我可以编写脚本来执行多个screen个会话没有我必须一个接一个地手动,启动每个会话然后分离,然后进入下一个屏幕会话。

此脚本取决于所设置的某些环境变量。通常,当我在screen之外的常规bash shell中运行此脚本时,我只需在.bash_profile文件中设置这些环境变量。

此外,当我以非分离状态启动屏幕并放入我的.screenrc文件时:

shell -$SHELL

然后我也没有问题。

只有当我执行screen -dm然后我的脚本无法运行时才会出现问题,因为我没有设置我需要的环境。

如何在分离状态下启动时让屏幕引用.screenrc文件,以便最终在启动时获取.bash_profile

更新

当我执行screen -dmL env时,我可以看到一些但不是所有的环境变量都存在。

2 个答案:

答案 0 :(得分:2)

不需要〜/ .screenrc
让你的〜/ .bash_profile一行:source ~/.bashrc
将别名和environemnt变量放在〜/ .bashrc

在〜/ .bashrc中,编写如下代码:

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"
}

现在在您的终端中测试

$ run_myalias_in_bg_screen
$ screen -r mytestscreen

答案 1 :(得分:1)

我认为您的问题是,在分离模式下启动screen时,screen无法启动登录shell或交互式shell,因此您的.bash_profile未获取(请参阅man bash的“INVOCATION”部分,用于解释启动时源文件的说明。请注意

中的前导-
shell -$SHELL

设置意味着shell将始终作为登录shell启动,因此将.bash_profile来源。

您问题的一些可能解决方案:

  1. 不要以分离状态启动screen。请注意,如果脚本作为命令提供,则在以常规方式启动脚本时,screen将终止。例如,对于脚本test.sh

    #!/bin/bash
    
    for n in `seq 1 5`; do
      echo $n
      sleep 1
    done
    

    执行screen ./test.sh运行脚本并在5秒后终止。

  2. 在您在屏幕中运行的脚本中手动获取.bash_profile。即添加

    source ~/.bash_profile
    

    到您的脚本开头MyScript

  3. 更新1

    我仍然怀疑问题是您的.bash_profile未加载,因此请确保您的.screenrc 正在加载。尝试添加

    screen touch /tmp/when-was-screen-rc-sourced
    

    ~/.screenrc的末尾,然后执行

    screen MyScript
    

    然后

    ls -lt --full-time /tmp
    

    尝试以几种不同的方式启动屏幕,看看~/.screenrc是否真的无法加载。

    同样,您可以添加一行

    touch /tmp/when-was-bash-profile-sourced
    

    ~/.bash_profile的末尾以查看何时加载。

    更新2

    这是一个示例,显示当您拥有行

    screen会运行您的脚本
    screen touch /tmp/when-was-screen-rc-sourced
    

    ~/.screenrc

    的末尾

    以下是测试文件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
    

    这是证据。运行

    $ touch /tmp/when-did-we-start; screen -d -m ./test.sh; sleep 6; ls -ltr --full-time /tmp | tail -n4
    

    给出输出

    -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
    

    所以,我仍然认为这个问题与你的~/.bash_profile有关 无论如何定义你缺少的env vars)都没有加载。

    更新3

    此时可能更容易理解你的确切内容 试图完成,然后想出一个更好的方法来做到这一点。至 这样做有助于您提供一个最小的例子 用于说明问题的脚本(即运行时它可以运行) 直接或在启动屏幕后手动,但不是直接运行时 通过screen ./example.shscreen -d -m ./example.sh)。

    但是,与此同时,这是另一个潜在的解决方法(你呢? 我试过上面的第二个原始建议,只是寻找你的 你的脚本中直接~/.bash_profile?):

    使用bash运行脚本,明确地将bash设为交互式 和/或登录shell。例如。对于交互式登录shell,请执行

    screen -d -m bash -i -I ./MyScript
    

    请参阅 here 有关哪些文件bash以什么模式加载的很好的总结。根据 到man bashbash -i -I组合应该让bash运行你的 交互式登录模式下的脚本,因此~/.bash_profile应该 得到来源。