【问题标题】:Is there a way to source arbitrary bash scripts (ie. msys2-packages "shell") in zsh?有没有办法在 zsh 中获取任意 bash 脚本(即 msys2-packages “shell”)?
【发布时间】:2018-02-12 15:26:44
【问题描述】:

我在 MSYS2 项目内部使用make,一般没有问题。但是,如果我使用 zsh,我将无法切换子系统。例如:

source shell mingw64

给予:

/usr/bin/shell:58: bad substitution

显然,shell 脚本中有特定于 bash 的代码,并且该脚本是有源代码的,因为它在调用 shell 中设置了环境变量。

可以修复此修改 shell 代码,但在下一个 pacman -Syu 之后可能会被覆盖或变得不兼容。

是否有在 zsh 中获取 Bash 脚本的通用解决方案(或特定于切换 MSYS 子系统的解决方案)?

【问题讨论】:

  • 如果你关心这个,你可能应该向github.com/AlexPux/MSYS2-packages 提出拉取请求。
  • 目前,尚不清楚make 在其中扮演什么角色。是否从Makefile 调用了source 命令?你能提供一个minimal reproducible example吗?如果您的source shell mingw64 命令 MCVE,那么Make 与该问题有什么关系?
  • @CharlesDuffy:是的,MCVE 是在 zsh 中执行的 source shell mingw64。我提到make 是因为使用 MSYS2 的令人信服的原因是在 Windows 中“制作”GNU/POSIX 程序的二进制文件。您在 mingw 子系统下获得 POSIX 仿真,并且本机二进制文件切换到 mingwXX 子系统。当然,没有什么可以阻止使用 MSYS2 只是为了使用 Linux shell 的乐趣,例如 zsh。在后一种情况下,shell 不起作用。我不是在问如何从 bash 中获取 zsh,因为我认为没有通用的解决方案。但是,应该也可以从 zsh 切换 MSYS2 子系统。
  • @antonio, ...这就是为什么上游有一个开放的票证要求 msys shell 命令的版本与所有符合 POSIX 的 shell 兼容。无论如何,据我所知,如果没有将 Windows 系统放在一起(或审核 shell 命令的源以确定它是否执行任何无法通过环境继承的事情),我已经回答了您的问题;如果您使用给定的bash -c 命令,它应该启动一个新的 zsh shell,配置为为 mingw64 目标构建软件。

标签: bash zsh msys2 mingw-w64


【解决方案1】:

您无法在 zsh 中解释任意 bash 脚本,但您可以启动一个新的 bash 副本,其中包含获取脚本的说明,然后将控制权交给 zsh 解释器:

bash -c 'set -a; source shell mingw64 && exec zsh -i'

因此,zsh 解释器将继承导出的环境变量和通过采购 bash 脚本所做的工作目录更改;它不会继承shell本地(非导出)变量、别名或函数。

set -a 指示 bash 默认导出所有变量,从而确保由源脚本设置的变量尽可能放置在环境中,而不是保持在 shell 本地。这不适用于无法导出的类型的值(例如数组),但这是一种合理的临时措施。


顺便说一句——有一个upstream ticket 要求此代码与/bin/sh 兼容。如果发生这种情况,zsh 将能够在 POSIX 兼容模式下解释它,您可以暂时输入如下:

emulate sh -c 'source shell mingw64'

【讨论】:

  • 出于某种原因:x=123bash -c 'set -a; source shell mingw64 && exec zsh -iecho $x 不给 123。另外,在一些子系统切换之后,会出现很多zsh进程。所以应该添加一个kill -9 parent-shell-pid(也许通过一个zsh函数/别名包装shell
  • @antonio,在调用bash之前需要export x,或者在定义变量之前使用set -a启用自动导出。不,你绝对不想杀死你的父进程——如果你不想留下一个,使用exec用子进程替换当前shell而不是留下一个父进程根本落后; exec bash -c 'set -a; source shell mingw64 && exec zsh -i' 根本不会增加内存中正在运行的进程的数量,因为旧的 zsh 实例用 bash 替换了自己,然后它又用 zsh 替换了自己。
  • @antonio, ...即使杀死一个进程是个好主意,顺便说一句,kill -9 几乎普遍不是 - 它会阻止您的进程能够自行清理,并且仅当存在阻止它的故障时才应使用(即,如果清理过程本身挂起)。使用 SIGTERM,而不是 SIGKILL,除非您有非常令人信服的理由不这样做。
猜你喜欢
  • 1970-01-01
  • 2016-03-18
  • 1970-01-01
  • 2020-09-30
  • 2012-12-31
  • 2014-01-08
  • 1970-01-01
  • 2020-01-08
  • 1970-01-01
相关资源
最近更新 更多