在调用shell中设置环境变量的最佳方法

时间:2022-05-29 23:06:33

I'm writing a utility that needs to be able to set and use context. I'd like it to use environment variables in the shell so that it can remember what context it's currently in between invocations. Ideally, I'd like to set this environment variable from within the utility itself. Something like:

我正在编写一个实用程序,它需要能够设置和使用上下文。我希望它在shell中使用环境变量,以便它能够记住当前调用之间的上下文。理想情况下,我希望在实用程序本身中设置这个环境变量。喜欢的东西:

mytool set-context <context>
mytool do-stuff # Aware of <context>

I'd like this to behave like:

我想这样做:

export MYTOOL_CONTEXT=<context>
mytool do-stuff # Aware of <context>

Now, it's not actually possible for a program to set environment variables in the environment of the calling shell (covered on SO here). However, that's the sort of behavior I want, and I'm looking for an approximation or workaround.

现在,程序实际上不可能在调用shell的环境中设置环境变量(这里已经介绍了)。然而,这正是我想要的行为,我正在寻找一种近似或变通方法。

Some ideas I had in mind:

我有一些想法:

  • Output the proper string, and expect the user to set the variable (assuming that the variable isn't simply set to <context>, but instead to some string derived from it). That would look something like export MYTOOL_CONTEXT=$(mytool get-context-var <context>).
  • 输出适当的字符串,并期望用户设置变量(假设变量不是简单地设置为 ,而是设置为从中派生的某个字符串)。它看起来类似于export MYTOOL_CONTEXT=$(mytool get-context-var )。
  • Output the full command for setting it. That would look something like $(mytool set-context <context>), where the output of the command is actually executed (and the output would be something like export MYTOOL_CONTEXT=<context>).
  • 输出设置它的完整命令。它看起来像$(mytool set-context ),实际上执行命令的输出(输出类似于export MYTOOL_CONTEXT= )。
  • Save to a temporary file whose name is based on the PID of the shell. This would work in most cases, but removing the file wouldn't happen automatically, so it would probably just lie around until reboot (ie, possibly forever on many machines).
  • 保存到一个临时文件,该文件的名称基于shell的PID。这在大多数情况下都是可行的,但是删除文件不会自动发生,所以它可能会一直拖到重新启动(也就是说,在许多机器上可能永远都是这样)。

Any other ideas? Thanks!

任何其他想法?谢谢!

Note: The above examples use BASH syntax, but there are equivalents in most shells.

注意:上面的例子使用BASH语法,但是在大多数shell中都有相同的用法。

1 个解决方案

#1


3  

Before clarification

The POSIX shells (bash, ksh, etc) and the Bourne shell allow you to set environment variables on a command line for one command only:

POSIX shell (bash、ksh等)和Bourne shell允许您仅为一个命令在命令行上设置环境变量:

MYTOOL_CONTEXT=<context> mytool do-stuff

This sets MYTOOL_CONTEXT as an environment variable for that invocation of mytool (only). Incidentally, most shells accept an option -k (which is not standardized by POSIX) that means all arguments that look like VAR=value are treated as environment variables, even when they appear after the command name. This is a curiosity with rather limited practical value, which is why it is not standardized.

这将MYTOOL_CONTEXT设置为mytool调用的环境变量(仅)。顺便说一句,大多数shell都接受选项-k (POSIX没有对其进行标准化),这意味着所有看起来像VAR=value的参数都被视为环境变量,即使它们出现在命令名之后。这是一种具有相当有限的实用价值的好奇心,这也是为什么它没有标准化的原因。

The POSIX env command is designed to allow you to control the environment of an invoked command, though it is commonly used without any arguments to list the current environment. So, alternatively, you might use:

POSIX env命令被设计为允许您控制被调用命令的环境,尽管它通常不使用任何参数来列出当前环境。因此,您也可以使用:

env MYTOOL_CONTEXT=<context> mytool do-stuff

The advantage of env is that you can do things like unset every environment variable before setting the ones specified in the command line (so you get total control over the environment).

env的优点是,您可以在设置命令行中指定的环境变量之前取消对每个环境变量的设置(因此您可以对环境进行完全控制)。

After clarification

If the intention is to set the environment for subsequent use, then the . command is the one to use. You can create a file, context, which contains commands to be executed to set the environment. Then you can use:

如果目的是为后续使用设置环境,则命令就是要使用的。您可以创建一个文件context,其中包含要执行的命令来设置环境。然后您可以使用:

. context

and the contents of the file will executed in the context of the current shell, so you can set environment variables, etc. Bash provides a synonym, source, for the . command. It was inspired by the C shell which does not provide the . command but does provide source as an equivalent. The file named as an argument to the . command will be searched for on $PATH but does not need to be executable (readable is sufficient). If you provide extra arguments, they become the positional parameters ($1, etc) for the duration of the . command. Note too that any variables or functions created by the dotted file remain in effect when the file is finished (unlike variables in a normal script which vanish when the script completes). If you aren't going to pollute the user's name space, you have to be careful.

文件的内容将在当前shell的上下文中执行,因此您可以设置环境变量等。命令。它的灵感来自于C壳,它不提供。命令,但是提供源文件作为等价的。作为参数命名的文件。将在$PATH中搜索命令,但不需要可执行(可读性就足够了)。如果您提供了额外的参数,那么它们将成为持续时间内的位置参数($1,等等)。命令。还要注意点文件创建的任何变量或函数在文件完成时仍然有效(不像普通脚本中的变量在脚本完成时消失)。如果您不想污染用户的名称空间,您必须小心。

#1


3  

Before clarification

The POSIX shells (bash, ksh, etc) and the Bourne shell allow you to set environment variables on a command line for one command only:

POSIX shell (bash、ksh等)和Bourne shell允许您仅为一个命令在命令行上设置环境变量:

MYTOOL_CONTEXT=<context> mytool do-stuff

This sets MYTOOL_CONTEXT as an environment variable for that invocation of mytool (only). Incidentally, most shells accept an option -k (which is not standardized by POSIX) that means all arguments that look like VAR=value are treated as environment variables, even when they appear after the command name. This is a curiosity with rather limited practical value, which is why it is not standardized.

这将MYTOOL_CONTEXT设置为mytool调用的环境变量(仅)。顺便说一句,大多数shell都接受选项-k (POSIX没有对其进行标准化),这意味着所有看起来像VAR=value的参数都被视为环境变量,即使它们出现在命令名之后。这是一种具有相当有限的实用价值的好奇心,这也是为什么它没有标准化的原因。

The POSIX env command is designed to allow you to control the environment of an invoked command, though it is commonly used without any arguments to list the current environment. So, alternatively, you might use:

POSIX env命令被设计为允许您控制被调用命令的环境,尽管它通常不使用任何参数来列出当前环境。因此,您也可以使用:

env MYTOOL_CONTEXT=<context> mytool do-stuff

The advantage of env is that you can do things like unset every environment variable before setting the ones specified in the command line (so you get total control over the environment).

env的优点是,您可以在设置命令行中指定的环境变量之前取消对每个环境变量的设置(因此您可以对环境进行完全控制)。

After clarification

If the intention is to set the environment for subsequent use, then the . command is the one to use. You can create a file, context, which contains commands to be executed to set the environment. Then you can use:

如果目的是为后续使用设置环境,则命令就是要使用的。您可以创建一个文件context,其中包含要执行的命令来设置环境。然后您可以使用:

. context

and the contents of the file will executed in the context of the current shell, so you can set environment variables, etc. Bash provides a synonym, source, for the . command. It was inspired by the C shell which does not provide the . command but does provide source as an equivalent. The file named as an argument to the . command will be searched for on $PATH but does not need to be executable (readable is sufficient). If you provide extra arguments, they become the positional parameters ($1, etc) for the duration of the . command. Note too that any variables or functions created by the dotted file remain in effect when the file is finished (unlike variables in a normal script which vanish when the script completes). If you aren't going to pollute the user's name space, you have to be careful.

文件的内容将在当前shell的上下文中执行,因此您可以设置环境变量等。命令。它的灵感来自于C壳,它不提供。命令,但是提供源文件作为等价的。作为参数命名的文件。将在$PATH中搜索命令,但不需要可执行(可读性就足够了)。如果您提供了额外的参数,那么它们将成为持续时间内的位置参数($1,等等)。命令。还要注意点文件创建的任何变量或函数在文件完成时仍然有效(不像普通脚本中的变量在脚本完成时消失)。如果您不想污染用户的名称空间,您必须小心。