GNU Screen不会在10.5.8上继承我的PATH


11

我每天都使用屏幕来满足终端的需求,对此我感到非常满意。不过,最近我做了一些更新我的bash配置文件和我注意到,我设置各种PATH元素(PATHMANPATHINFOPATH在2个地方,等)。我将文件修改为应有的样子,现在我的所有环境变量都已设置一次.bash_profile。这就是我的问题。

显然,我之所以将它们设置在两个位置是因为屏幕。屏幕似乎仅执行.bashrc,似乎没有PATH从原始bash shell正确继承我的或任何其他环境变量。因为它仅执行,.bashrc并且我现在仅将变量设置为in .bash_profile,所以我得到的不完整PATH

那么,我的问题是如何在不进行复制的情况下将环境变量显示到屏幕上。阅读Bash文档似乎表明它可能是屏幕用于登录的外壳类型,即非登录交互式外壳,但是我不知道如何强制屏幕使用特定类型的外壳,只有通过使用的shell -s /bin/bash

您可以在GitHub页面上仔细阅读我的配置文件。 这是打破屏幕的提交提交

编辑:我正在使用,Screen version 4.00.03 (FAU) 23-Oct-06并且我倾向于通过screen -h 50000

编辑:我现在已经能够在Cygwin()上进行测试CYGWIN_NT-5.1 1.7.1(0.218/5/3) i686Screen version 4.00.03 (FAU) 23-Oct-06并且它表现出与Mac上不同的行为。

我现在发现的特定行为是,在Cygwin中,我对PATH.bash_profile 所做的更改在进入屏幕时会被复制,然后连续创建屏幕窗口不会复制路径,而是重新提供.bash_profile。

为了说明我正在谈论的行为:

来自新终端的输出:

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

屏幕第一次调用的输出:

[~]$ screen -h 50000 -s -/bin/bash

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

随后的呼叫C-a c

...

PATH: /home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/home/tvishe01/bin/emacs/bin:/home/tvishe01/bin:/usr/local/bin:/usr/bin:/bin:/cygdrive/c/WINDOWS/system32:/cygdrive/c/WINDOWS:/cygdrive/c/WINDOWS/System32/Wbem:/cygdrive/c/Program Files/ATI Technologies/ATI.ACE/Core-Static:/groovy-1.6.1/bin:/usr/lib/lapack

MANPATH: /home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man:/home/tvishe01/share/man:/usr/local/man:/usr/share/man:/usr/man::/usr/ssl/man:/usr/ssl/man

Aliases:
alias ..='cd ..'
alias ...='cd ../..'

...

[~]$

你可以看到


重复是因为您已将bash配置为无条件添加这些条目,并且它是一个'login'shell,并且您正在告诉屏幕bash作为' login'shell进行调用。我重写了答案,以尝试解决shell,screen和环境变量的一般问题。
克里斯·约翰森

Answers:


16

屏幕和环境变量

默认情况下,屏幕将在会话启动时传递给它的外壳(和其他进程)任何环境变量(即重新连接不会更改为新外壳提供哪些环境变量)。但是,由于屏幕和外壳的配置文件通常都会更改环境变量,因此在很多地方都可能引入意外的更改。有一些变量,例如TERM,它的屏幕几乎总是在变化,但是这些通常是屏幕提供的功能所必需的。

假设您的外壳程序配置或screen的配置都不会修改名为FOOBAR的变量(很可能,总之)。如果使用开始会话FOOBAR=foo screen,则在该会话中创建的所有外壳程序都将具有一个名为FOOBAR的环境变量,其值为foo

对于屏幕或您的外壳可能修改的变量,事情变得更加复杂。

使用屏幕时缺少设置

登录外壳

如果您发现由screen启动的外壳中缺少某些设置,可能是因为您的外壳仅配置为更新“登录”外壳的那些设置。大多数shell都知道可以配置屏幕使用的特殊约定(在C:中**argv == '-')。

根据屏幕文档

外壳 命令

设置用于创建新外壳的命令。这将覆盖环境变量$ SHELL的值。如果您想运行一个tty-enhancer,它希望执行$ SHELL中指定的程序,这将很有用。如果命令以“-”字符开头,则外壳程序将作为登录外壳程序启动。

屏幕开始壳为“登录”炮弹,开始屏幕screen -s -/bin/bash,或该行添加到您的.screenrc

shell -/bin/bash

调整到碰巧要使用的shell的路径。

屏幕配置

缺少或重置环境变量也可能是由于屏幕配置文件中的setenvunsetenv命令所致。您将必须同时检查主目录中的.screenrc屏幕编译用作“系统screenrc”的文件(您可以尝试使用类似查找在编译时配置的路径名的命令-通常为/ etc / screenrc用于系统安装的屏幕;附加安装可能会使用其他路径名)。您可以使用来临时避免使用这些设置文件,但是有一个编译时选项会阻止有效使用SYSSCREENRCstrings "$(which screen)" | fgrep -i screenrcSCREENRC=/dev/null SYSSCREENRC=/dev/null screen (大概是为了让系统管理员可以强制执行一些初始配置)。

使用屏幕时重复设置

在外壳程序的配置文件中,将项目添加到环境变量(例如PATH)中是很常见的,以便更新的值可用于常规外壳程序会话(例如xterm或其他终端窗口,控制台会话等)。如果将这些项目添加到外壳程序的每个外壳程序配置中(或者,如果您使用上述-/path/to/shell设置,则在外壳程序每个登录配置中),则按屏幕启动的外壳程序将可能具有所添加项目的多个副本。

避免这种情况的一种策略是将所有添加项添加到shell的per-login配置中的PATH之类的变量中,并避免将-/path/to/shellshell设置与screen一起使用

另一种策略是仅有条件地将新项目添加到变量。根据外壳的不同,执行此操作的代码可能会有些复杂,但是通常可以将其封装在外壳函数中以方便使用。

另一种策略是始终从配置文件中的固定值开始。当默认值可能相差很大时,将配置文件从一个系统移动到另一个系统时,有时可能会导致问题。

诊断程序

如果您不能直接发现发生特定修改的位置,则可以尝试以下方法来跟踪发生更改的位置。

检查初始外壳中的当前值:

echo "$PATH"

检查创建子外壳程序时外壳程序本身如何修改值:

/bin/bash -c 'echo "$PATH"'

检查创建“ login”子shell时shell如何修改值:

perl -e '$s=shift;exec {$s} "-$s", @ARGV or die "unable to start shell"' /bin/bash
echo "$PATH"
exit

检查屏幕如何修改值:

printf '#!/bin/sh\nl=/tmp/echo-var.log;rm -f "$l"; echo $PATH >"$l"' >/tmp/echo-var &&
chmod a+x /tmp/echo-var &&
screen -s /tmp/echo-var &&
cat /tmp/echo-var.log

这解决了部分问题。不幸的是,它并没有完全解决。现在,屏幕可以正常运行,screen -s -/bin/bash但是它不能像我期望的那样在我的工作机上运行于Cygwin。在那台机器上,我运行了screen -h 50000,它只是继承了我PATH的文件,而没有再次实际获取文件。每次我启动新窗口时都会运行。
蒂姆·维舍

屏幕进程的环境应始终被其子进程的任何子进程继承(除了可能覆盖的TERM之类的东西)。尝试FOOBAR=baz screen并检查echo $FOOBAR从shell窗口screenscreen -s -/bin/bash。两个变体都应具有FOOBAR= baz。如果您PATH正在修改,那么您将必须跟踪正在执行的操作。请尝试SYSSCREENRC=/dev/null SCREENRC=/dev/null screen,如果可以PATH通过,则可能是setenv PATHin /etc/screenrc~/.screenrc。否则,这就是您.bashrc正在做的事情。
克里斯·约翰森

我对答案做了很大的改写。
克里斯·约翰森

2

上次看到类似问题时,我通过screen -l在启动屏幕时使用来解决了。

您可以-l在调用时使用该选项screen(打开登录模式;也由中的defloginlogin命令控制.screenrc)来设置屏幕是否默认情况下应登录窗口(添加/删除/ etc / utmp条目)。

默认情况下,登录模式是打开的,但是可以在编译时更改。如果未使用utmp支持编译screen,则这些命令不可用。

我似乎不需要-lDebian Lenny的默认屏幕(v4.0.3)中的模式;它似乎默认情况下处于启用状态。我的~/.profile~/.bashrc正在正确阅读。您如何调用screen?您使用的是哪个版本?


寿这一理论下,screen -ln应该跑我的~/.profile,它仍然被运行。因此请尝试-l标记,但这可能不是正确的答案。暂时将其留在这里。
quack quixote 2010年

似乎-l只能控制是否screen将条目添加到utmp文件,而不控制它是否使用自己的-l选项调用新的shell 或使用exec- with - -prefix自定义。
克里斯·约翰森


1

从.bash_profile中采购.bashrc并没有错。如果您仅在本地使用计算机,则在大多数情况下,.bash_profile仅在您进行首次登录时才被获取(显然还有其他时间被获取)。

我对文件进行整理,以便仅在登录时才执行某项操作,因此将信息存储在.bash_profile中,将其他所有信息都存储在.bashrc中。PATH是我放入.bashrc中的一件事,并且我在.bash_profile中提供了.bashrc。


您是否愿意将您的.bashrc.bash_profile文件发布到某个地方,以便我可以看到它们?我在执行类似操作时遇到的问题是,PATH每当我创建一个新的屏幕实例时,该问题就会增加,因为它将继承旧的屏幕实例PATH,然后再次重新添加所有内容。
蒂姆·维舍

抱歉,蒂姆,我没看到这个……我已经改变了很多事情,所以它们没有多大意义,但这基本上是我要做的。#.bash_profile如果[-f〜/ .bashrc]; 然后 。〜/ .bashrc fi然后,我将其他所有内容都放在.bashrc中,除了我首次登录时要启动的内容(也包含在.bash_profile中)。PATH在.bashrc中以一系列行而不是一个路径定义的方式进行处理,就像大多数情况一样,导出PATH = / path / to / binaries1:$ PATH export PATH = / path / to / binaries2:$ PATH

0

每当我有一些问题,像我创建了一个文件$HOME/.debug,并在所有文件的来源/登录/ shell调用期间执行(例如~/.bashrc~/.bash_profile~/.profile/etc/bashrc,等),我作为一线

test -f $HOME/.debug && echo $HOME/.bashrc 1>&2

或类似。对于特定的调试,您还可以添加类似

test -f $HOME/.debug && echo PATH now equals $PATH 1>&2

这样,您可以100%绝对确定使用了哪些文件。

重定向到stderr很重要,在很多情况下,您都不想使stdout混乱。


0

您可以继续使用.profile,因为系统不会接触bashrc(例如图形会话)。现在,您仅拥有两组不同的环境,一组来自.profile,另一组来自.bashrc。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.