我怎么能够安全地从 ksh 脚本中获取 ksh 版本?
我有看到了以下解决方案:
ksh --version
echo ${.sh.version}
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
,我们可以尝试以下步骤:
- 检查
KSH_VERSION
以检测mksh
,pdksh
,lksh
- 如果第一步失败,请尝试
ksh93
和之间不同的功能ksh88/86
(让大卫·科恩向我们展示)。
考虑到这些,我将:
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 版本方面,通常已被证明非常可靠,但事实证明,编写脚本更加困难。