Sil*_*eth 13 ksh version shell-script portability
如何从 ksh 脚本中安全地获取 ksh 版本?
我已经看到以下解决方案:
ksh --versionecho ${.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
Run Code Online (Sandbox Code Playgroud)当然echo $KSH_VERSION看起来工作正常——我的意思是它不会崩溃——尽管在这些机器上它是空白的。另外,我看到的地方是KSH_VERSION只被设定pdksh。
问题:
ksh编程方式安全地检查版本?出于我的目的,我并不真正关心实际的版本号是什么,只关心它是否是ksh.$KSH_VERSION足够好?我的意思是如果它是空白的,那么ksh一定是过时的版本吗?其他论坛是否正确,即使对于较新版本的ksh.KSH_VERSION在ksh9393t 版本之前没有实现。它将被设置在mksh、pdksh、 中lksh。因此,为了检查 的版本ksh,我们可以尝试以下步骤:
KSH_VERSION以检测mksh, pdksh,lkshksh93和之间使用不同的功能ksh88/86(让 David Korn 向我们展示)。考虑到这些,我会选择:
case "$KSH_VERSION" in
(*MIRBSD*|*PD*|*LEGACY*) printf '%s\n' "$KSH_VERSION" ;;
(*) [ -z "$ERRNO" ] && printf '%s\n' "${.sh.version}" || echo ksh88/86 ;;
esac
Run Code Online (Sandbox Code Playgroud)
我认为.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
Run Code Online (Sandbox Code Playgroud)
KSH_VERSION 开始于公共域 ksh 克隆 (pdksh),并在 2008 年使用 ksh93t 添加到实际的 Korn shell。
与其测试版本号,不如测试让您感到痛苦的特定功能。大多数功能都可以通过在子 shell 中尝试一些构造来测试,看看它是否会触发错误。
对于“真实”ksh版本(即基于 AT&T),我使用以下命令:
strings /bin/ksh | grep Version | tail -2
Run Code Online (Sandbox Code Playgroud)
这是我得到的各种输出:
原始ksh:
@(#)Version M-11/16/88i
Run Code Online (Sandbox Code Playgroud)
dtksh;
@(#)Version 12/28/93
Version not defined
Run Code Online (Sandbox Code Playgroud)
现代ksh93:
@(#)$Id: Version AJM 93u+ 2012-08-01 $
Run Code Online (Sandbox Code Playgroud)
对于pdksh/msh ksh克隆和现代 AT&Tksh版本,这里有一些工作:
$ mksh -c 'echo $KSH_VERSION'
@(#)MIRBSD KSH R50 2015/04/19
Run Code Online (Sandbox Code Playgroud)
编辑:
我忽略了您是在询问从脚本内部执行此操作,而不是通过知道经过测试的 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)
Run Code Online (Sandbox Code Playgroud)
请注意,此方法不可靠,因为/proc可能无法安装,并且肯定还有其他弱点。它在其他 Unix 操作系统上未经测试。
当我为 编写脚本时ksh,我注意到旧版本的-a.ksh 内置whence命令选项似乎不受支持ksh。在我检查的所有系统上似乎都是如此,其中包括 Solaris、AIX、HP-UX 和 Linux。
所以这里是 ksh 函数的解决方案:
is_modern_ksh() {
if whence -a whence > /dev/null 2>&1 ; then
return 0 #success -> true
fi
#Else the call to `whence` failed because `-a` is not supported
return 1 #failure -> false
}
Run Code Online (Sandbox Code Playgroud)
使用方法如下:
if is_modern_ksh ; then
echo "You're using a MODERN version of ksh. :)"
else
echo "You're using an OLD version of ksh. :("
fi
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
23781 次 |
| 最近记录: |