我试图编写一个shell脚本,当运行时,将设置一些环境变量,这些变量将在调用者的shell中保持设置。

setenv FOO foo

在csh/tcsh中,或

export FOO=foo

在sh/bash中只在脚本执行期间设置它。

我已经知道了

source myscript

将运行脚本的命令,而不是启动一个新的shell,这可能导致设置“调用者的”环境。

但问题是:

我希望这个脚本可以从bash或csh中调用。换句话说,我希望任何一个shell的用户都能够运行我的脚本,并更改他们的shell环境。因此,'source'对我来说不适用,因为运行csh的用户不能获取bash脚本的源代码,而运行bash的用户也不能获取csh脚本的源代码。

有没有合理的解决方案,不需要在脚本上编写和维护两个版本?


当前回答

通过使用gdb和setenv(3)是“有点”可能的,尽管我很难推荐实际这样做。(另外,最近的ubuntu不会让你这样做,除非告诉内核对ptrace更加宽容,其他发行版也可能会这样)。

$ cat setfoo
#! /bin/bash

gdb /proc/${PPID}/exe ${PPID} <<END >/dev/null
call setenv("foo", "bar", 0)
END
$ echo $foo

$ ./setfoo
$ echo $foo
bar

其他回答

您应该使用模块,参见http://modules.sourceforge.net/

编辑:模块包自2012年以来没有更新,但仍然可以正常工作。所有的新功能,铃声和口哨都发生在今天的lmod(我更喜欢它):https://www.tacc.utexas.edu/research-development/tacc-projects/lmod

在我的.bash_profile我有:

# No Proxy
function noproxy
{
    /usr/local/sbin/noproxy  #turn off proxy server
    unset http_proxy HTTP_PROXY https_proxy HTTPs_PROXY
}


# Proxy
function setproxy
{
    sh /usr/local/sbin/proxyon  #turn on proxy server 
    http_proxy=http://127.0.0.1:8118/
    HTTP_PROXY=$http_proxy
    https_proxy=$http_proxy
    HTTPS_PROXY=$https_proxy
    export http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
}

当我想禁用代理时, 函数在登录shell中运行并设置变量 正如预期和希望的那样。

你可以使用别名

alias your_env='source ~/scripts/your_env.sh'

这不是我所说的杰出的,但如果您需要从shell调用脚本,这也可以工作。这不是一个很好的解决方案,但对于一个单一的静态环境变量,它工作得足够好了。

1)。创建一个条件为0(成功)或1(不成功)的脚本

if [[ $foo == "True" ]]; then
    exit 0
else
    exit 1

2)。创建依赖于退出代码的别名。

alias='myscript.sh && export MyVariable'

调用别名,别名调用脚本,脚本计算条件,条件必须通过'&&'退出0,以便在父shell中设置环境变量。

这是垃圾,但在紧要关头可以派上用场。

另一个我没有提到的解决方法是将变量值写入文件。

我遇到了一个非常相似的问题,我希望能够运行最后一个集测试(而不是所有的测试)。我的第一个计划是编写一个命令来设置env变量TESTCASE,然后使用另一个命令来运行测试。不用说,我和你有同样的问题。

但后来我想到了这个简单的方法:

第一个命令(testset):

#!/bin/bash

if [ $# -eq 1 ]
then
  echo $1 > ~/.TESTCASE
  echo "TESTCASE has been set to: $1"
else
  echo "Come again?"
fi

第二个命令(testrun):

#!/bin/bash

TESTCASE=$(cat ~/.TESTCASE)
drush test-run $TESTCASE