【问题标题】:Set an environment variable within a shell alias在 shell 别名中设置环境变量
【发布时间】:2016-01-26 14:11:07
【问题描述】:

在我的系统上,我安装了两个版本的 Java - 有些程序需要 Java 7,有些需要 Java 8。

Java 8 是我的系统默认设置,所以当我运行 Java 7 命令时,我一直在使用:

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/ \
java_7_program

我想设置一个别名,这样我就可以写了

j7 java_7_program

我已经定义了:

alias j7='JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/'

但随后运行 j7 java -version 会产生:

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

man page(搜索“别名”)声明这是作为直接替换完成的。为什么这不起作用有什么原因吗?

bash --version 打印 GNU bash, version 4.3.42(1)-release (x86_64-apple-darwin14.5.0)

一个更孤立的例子(减去 java):

$ alias foo='BAR=baz'
$ type foo
foo is aliased to `BAR=baz'
$ foo echo $BAR
[blank line]

【问题讨论】:

  • 尝试foo env,您会看到 BAR 设置为 baz。也可以尝试foo /bin/echo $BAR,这应该可以。不同之处在于 echo 是内置的 shell,因此显式运行二进制文件是正确的。
  • 关于你的编辑:正如我已经说过的,当你输入foo echo $BAR,那么BAR不会在当前shell中设置,只在echo的环境中;并且$BAR 被扩展之前 echo 运行。尝试其中任何一个,您会发现它有效: 1. 在单独的行上输入foo,然后在后面输入echo $BAR,或者相当于foo; echo "$BAR"; 2.foo eval 'echo "$BAR"'; 3.(有点相似)foo bash -c 'echo "$BAR"'.
  • 好的,这里有几个问题。一个是我问的问题(为什么不是别名设置变量?),令人困惑的因素是运行java 使用/bin/java,它使用1.8 而不管JAVA_HOME 变量。
  • 重新阅读所有这些,看来您的问题只是来自使用引号'!只是鞭打报价:alias j7=JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/ 可以正常工作!
  • @F.Hauri 对我不起作用。如果您已经执行了不止一次(即j7 ; j7 echo $JAVA_HOME),那么它可以工作。

标签: bash shell environment-variables alias


【解决方案1】:

回答你孤立的例子:

当你做这样的事情时:

bar=foo my_command

然后bar 设置在my_command 的环境中(当前shell 看不到)。因此,当你这样做时:

bar=stuff
bar=foo my_command "$bar"

由于$bar的扩展发生在my_command执行之前,那么它就像在做:

bar=foo my_command stuff

因为$bar 被扩展之前 my_command 被分叉。这解释了您在示例中获得的[blank line]

$ alias foo='BAR=baz'
$ type foo
foo is aliased to `BAR=baz'
$ foo echo $BAR
[blank line]

只是为了好玩,试试这些:

$ alias foo=BAR=baz
$ BAR=something
$ foo echo "$BAR"
something

有意义吗?

$ alias foo=BAR=baz
$ foo eval 'echo "$BAR"'
baz

这是因为BAR 是在eval 的环境中传递的,然后echo "$BAR" 被扩展...具有预期值(注意单引号!)。

同样,

$ alias foo=BAR=baz
$ foo sh -c 'echo "$BAR"'
baz

【讨论】:

  • 谢谢。值得注意的是别名 foo='BAR=baz ;'也可以。
  • 但你不是说eval是邪恶的! ??
  • @F.Hauri:不,我没有:)……在这种情况下,它并不是真正的邪恶(它与上一个示例中的sh 一样邪恶/善良)。
【解决方案2】:

jdk1.7.*.jdk 位可能是问题所在。如果我在其中放入显式版本,则可以正常工作

您可以使用/usr/libexec/java_home -v 1.7 来安装最新的 1.7 版本。

所以要重做你的别名,试试:

alias j7='JAVA_HOME=`/usr/libexec/java_home -v 1.7`'

注意 java_home 位周围的反勾号,然后它将执行命令以生成将 JAVA_HOME 设置为的正确路径。

【讨论】:

  • 它对我不起作用。作为一个简化的示例:alias foo='BAR=baz' ; foo echo $BAR 打印一个空行。
  • @FabianTamp alias foo='BAR=baz'fooecho "$BAR" 在三个单独的行上(好吧,只有别名声明需要在单独的行上)。
  • @FabianTamp 我怀疑它不起作用。你的壳是什么?您真的在三个单独的行中输入了所有三个命令吗?
  • 是的。在这里也复制粘贴了输出,但它被换行符剥离搞砸了。 $ alias foo='BAR=baz' $ type foo foo is aliased to 'BAR=baz' $ foo echo $BAR [空白行]
  • Fabian,我认为这是因为 echo 在另一个 shell 中,通常 shell 变量不会通过。如果您尝试我的别名并执行 j7 java -version 会怎样 - 这适用于运行 10.10.5、bash 版本 3.2.57 的 Mac。
【解决方案3】:

在设置环境之前,Shell 别名不能用于执行任何操作。

Shell 别名只能包含普通命令,不能包含 jockersub 命令

为了做这样的事情,你必须写一个wrapper脚本或者至少一个函数

sudo cat >/usr/local/bin/j7 <<<eof
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/
java $@
eof
sudo chmod +x /usr/local/bin/j7

或将此函数定义添加到您的.bashrc

j7() {
  export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.*.jdk/Contents/Home/
  java $@
}

真正有用的 bash 包装器

类似:

j7 () {
    local JLIBROOT dir
    # JLIBROOT=/usr/lib/jdk
    JLIBROOT=/Library/Java/JavaVirtualMachines
    while read dir && [ "$dir" = "${dir//1.7.}" ] ;do
        :
      done < <(
          /bin/ls -1trd $JLIBROOT/*
    )
    if [ "$dir" != "${dir//1.7.}" ] ;then
          export JAVA_HOME=$dir/Contents/Home
          java $@
      else
          echo "Version 1.7 not found in '$JLIBROOT'."
      fi
}

可以在我的 Linux 桌面上运行...

【讨论】:

  • 为什么说不能用shell别名来修改环境呢?因为它可以...alias abc='PATH=somewhere' 然后abc 然后declare -p PATH... 也可以在 POSIX shell 中工作(但显然不能使用declare 来查看变量)。
【解决方案4】:

使用env

您可以使用env 实用程序设置环境。

alias foo='env - X=42 perl -E"say \$ENV{X}"'

这会设置一个别名foo,它声明环境变量X,并在执行perl之前将其初始化为42,并指示它打印出环境变量X

【讨论】:

    猜你喜欢
    • 2018-06-27
    • 2012-10-01
    • 2014-10-27
    • 2013-09-04
    • 1970-01-01
    • 2015-01-03
    • 2013-01-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多