如何安全地获取 ksh 版本?

如何安全地获取 ksh 版本?

我怎么能够安全地从 ksh 脚本中获取 ksh 版本?

我有看到了以下解决方案:

  1. ksh --version
  2. echo ${.sh.version}
  3. echo $KSH_VERSION

在适当的情况下,这些都可以正常工作。然而,我关心的是不完美的情况。

具体来说,我使用的几台机器都装有旧版本的 ksh,就我的目的而言,这些机器严重缺乏功能。无论如何,我想(以编程方式)检查版本的原因是查看 ksh 版本是否是功能较弱的版本之一;如果是这样,我想执行一个代码不太好的分支。

然而,在有问题的机器上,shell 的无能扩展到检查版本......

  • 如果我尝试ksh --version,它不会打印任何内容并打开一个新实例ksh
  • 如果我尝试echo ${.sh.version}ksh则会将其视为语法错误,无法使用2> /dev/null.

    $ echo ${.sh.version} 2> /dev/null  
    ksh: ${.sh.version}: bad substitution
    
  • 当然echo $KSH_VERSION看起来工作正常——我的意思是它不会崩溃——尽管在这些机器上它是空白的。另外,我还看到了某处KSH_VERSION仅由设定pdksh

问题:

  • 如何以编程方式安全地检查版本ksh?就我的目的而言,我并不关心实际的版本号是什么,只关心它是否是过时的版本ksh
  • $KSH_VERSION好吗?我的意思是,如果它是空白的,那么ksh一定是过时的版本吗?其他论坛是否正确,即使对于较新版本的 ,也可能无法设置它ksh
  • 难道就没有办法检查这个吗?

答案1

KSH_VERSION在93t之前的版本中没有实现ksh93。它将设置在mksh, pdksh,中lksh。因此,为了检查 的版本ksh,我们可以尝试以下步骤:

考虑到这些,我将:

case "$KSH_VERSION" in
  (*MIRBSD*|*PD*|*LEGACY*) printf '%s\n' "$KSH_VERSION" ;;
  (*) [ -z "$ERRNO" ] && printf '%s\n' "${.sh.version}" || echo ksh88/86 ;;
esac

答案2

我认为.sh.version自从 ATT ksh 93 的第一个版本以来就已经存在了。它在 pdksh 或 mksh 中不可用。由于 是${.sh.version}ksh93 以外的 shell 中的语法错误,因此请将其测试包装在子 shell 中并将其保护在eval.

_sh_version=$(eval 'echo "${.sh.version}"' 2>/dev/null) 2>/dev/null
case $_sh_version in
  '') echo "This isn't ATT ksh93";;
esac

KSH_VERSION最初出现在公共域 ksh 克隆 (pdksh) 中,并于 2008 年通过 ksh93t 添加到实际的 Korn shell 中。

您不应该测试版本号,而应该测试给您带来痛苦的特定功能。大多数功能可以通过在子 shell 中尝试某些构造并查看它是否触发错误来测试。

答案3

对于“真实”ksh版本(即基于 AT&T),我使用以下命令:

strings /bin/ksh | grep Version | tail -2 

以下是我得到的各种输出:

原来的ksh:

@(#)Version M-11/16/88i

dtksh;

@(#)Version 12/28/93
Version not defined

现代 ksh93:

@(#)$Id: Version AJM 93u+ 2012-08-01 $

对于pdksh/msh ksh克隆和现代 AT&Tksh版本,以下是有效的:

$ mksh -c 'echo $KSH_VERSION'
@(#)MIRBSD KSH R50 2015/04/19

编辑:

我忽略了您询问的是从脚本内部执行此操作,而不是通过了解测试的 ksh 二进制文件的路径。

假设您确实想要使用的版本ksh,而不是它支持的功能,那么这是一种仅使用strings至少应在 Linux 和 Solaris 上运行的命令来完成此操作的方法:

echo $(for i in $(find /proc/$$ ! -type d ! -name "pagemap" | 
  grep -v "/path/" | grep -v "/fd/" ) ; do
  strings $i | egrep "([V]ersion|[K]SH_VERSION).*[0-9]" | sort -u
done 2>/dev/null)

请注意,此方法不可靠,因为/proc可能无法安装,并且肯定还有其他弱点。它未经其他 Unix 操作系统的测试。

答案4

CTRL+ ALT+V

或者

ESC, CTRL+V

在以交互方式确定您正在使用的 KSH 版本方面,通常已被证明非常可靠,但事实证明,编写脚本更加困难。

相关内容