实际上我想运行 2 个 bat 脚本,第一个脚本将设置一个系统变量 set NEWPATH="E:/Some"
第二个脚本将显示该变量的路径:echo %NEWPATH%
。这不是第一次使用同一台服务器,当我重新启动将显示路径的服务器时,否则它将不显示任何内容。那么有人可以帮助我吗?
最佳答案
我没有完全理解你的问题,但这里有一些观察结果。
一些理论
在批处理文件(由 shell 进程
cmd.exe
执行)或任何其他类型的进程中设置的环境变量只能为 设置正是这个过程。也就是说,每个进程都有一个特殊的 block ,其中包含在创建该进程时由操作系统提供给它的环境变量。
这也意味着当设置环境变量的进程完成时,它的环境 block 就消失了。
环境变量可以由设置该环境变量的进程启动的进程继承。
你的情况会怎样
这意味着如果你按顺序运行两个批处理脚本,这意味着
第一个
cmd.exe
进程被调用,它执行的批处理脚本 设置环境变量;那么这个进程就没有了,它的环境 block 也没有了。然后启动另一个
cmd.exe
,它继承了您的主机进程(编写 Go)的环境 block ,但是如您所见,第一个批处理脚本设置的是不可用。
你能做些什么
有两种可能的方法来解决这个问题:
让第一个批处理脚本自己调用第二个。
在这种情况下,第二个
cmd.exe
将继承环境变量 由第一个脚本设置,因此将“看到”它们。请注意,Windows 批处理命令语言支持
调用
命令通过路径名调出其他批处理脚本。让第一个脚本将该变量的值传达给您的主机进程,然后在主机进程中为第二个
cmd.exe
安排指定的变量和指定的值它的环境。比如说,第一个脚本可以做类似的事情
echo VARNAME=value
有
VARNAME=value
打印到它的标准输出。
您的 Go 进程可以解析该输出,在
=
上将其拆分 字符,清理以不影响“有趣的”变量,如PATH
,USERPROFILE
等,然后主机进程可以做env := os.Environ() env = env.append("VARNAME=value") // real value here ... cmd := exec.Command(`cmd.exe`, `/c`, secondScriptFilePath) cmd.Env = env ... cmd.Run() // or whatever
第二种情况可以做的有点不同:宿主进程
可以调用os.Setenv("VARNAME=value")
让这个变量出现在它的
自己的环境 block ;然后它将被之后启动的任何进程自动继承。
更新以解决 OP 的评论
…script files will be in client side so i can't add a line
echo VARNAME=value
. so is there any other possible way to do this?
还有另一种方法可能适用于您的情况。
想法是 cmd.exe
只是一个外壳:当它以非交互方式启动时(这就是 exec.Command("cmd.exe")
所做的) >)
它从其标准输入流中读取命令并一条一条地执行它们——直到流被关闭(由发送者关闭)。
因此您可以执行以下操作:
启动
cmd.exe
,同时将io.Pipe
实例连接到它的Stdin
。自己打开第一个脚本,通过第一步设置的管道将其铲到正在运行的
cmd.exe
。不要忘记
Flush()
管道。您可以使用
io.Copy()
函数将所有数据从打开的io.Reader
发送到某个io.Writer
.保持 shell 实例运行。
到时候,读取第二个脚本并将它铲到同一个 shell 上。
由于 shell 是相同的,第二个脚本运行时就好像它物理上附加到第一个脚本上一样,并且会看到第一个脚本设置的所有变量。
关于batch-file - 在下一个批处理脚本运行中使用由批处理脚本设置的环境变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41391723/