如何克服Linux上的ksh与AIX / Solaris / HPUX上安装的ksh之间的不兼容?

时间:2020-03-05 18:56:30  来源:igfitidea点击:

我参与了将包含数百个ksh脚本的系统从AIX,Solaris和HPUX移植到Linux的过程。我在ksh在两个系统上的行为方式上遇到了以下差异:

#!/bin/ksh
flag=false
echo "a\nb" | while read x
do
    flag=true
done
echo "flag = ${flag}"
exit 0

在AIX,Solaris和HPUX上,输出为" flag = true";在Linux上,输出为" flag = false"。

我的问题是:

  • 我是否可以设置环境变量来使Linux的ksh像其他Os一样运行?失败:
  • Linux的ksh上是否有一种选项可以获取所需的行为?失败:
  • 是否有可用于Linux且具有所需行为的ksh实现?

其他说明:

  • 在AIX,Solaris和HPUX上,ksh是ksh88的变体。
  • 在Linux上,ksh是公共域ksh(pdksh)
  • 在AIX上,Solaris和HPUX dtksh和ksh93(在其中安装了它们)与ksh一致
  • 我可以访问的Windows NT系统:Cygwin和MKS NT与Linux一致。
  • 在AIX,Solaris和Linux上,bash一致,给出错误的结果(从我的角度来看)" flag = false"。

下表总结了系统存在的问题:

uname -s       uname -r                   which ksh          ksh version                     flag =
========       ========                   =========          ===========                     ======
Linux          2.6.9-55.0.0.0.2.ELsmp     /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
AIX            3                          /bin/ksh           Version M-11/16/88f             true    // AIX 5.3
                                          /bin/ksh93         Version M-12/28/93e             true
SunOS          5.8, 5.9 and 5.10          /bin/ksh           Version M-11/16/88i             true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
HP-UX          B.11.11 and B.11.23        /bin/ksh           Version 11/16/88                true
                                          /usr/dt/bin/dtksh  Version M-12/28/93d             true
CYGWIN_NT-5.1  1.5.25(0.156/4/2)          /bin/ksh           PD KSH v5.2.14 99/07/13.2       false
Windows_NT     5                          .../mksnt/ksh.exe  Version 8.7.0 build 1859...     false    // MKS

在我公司的一些人员提出建议之后,我们决定对代码进行以下修改。无论使用"真实的" ksh(ksh88,ksh93)还是任何ksh克隆(pdksh,MSK ksh),这都给我们相同的结果。这也可以与bash一起正常使用。

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

感谢jj33先前接受的答案。

解决方案

回答

我不知道有什么特定的选项可以强制ksh与特定的较旧版本兼容。就是说,也许我们可​​以在Linux机器上安装非常旧的ksh版本,并且其行为是否兼容?

在AIX / HP-UX盒子上安装更新版本的amy shell可能会更容易,而只需迁移脚本以使用sh。我知道有适用于所有平台的bash版本。

回答

不要在Linux上使用pdksh,而要使用kornshell.org中的" real" ksh。 pdksh是ksh的盲目重新实现。 kornshell.org是可追溯到25年左右的原始korn外壳(由David Korn编写)。 AIX和Solaris使用原始ksh的版本,因此kornshell.org版本通常是feature和bugcomplete。在使用SunOS / Solaris之后,安装kornshell.org ksh通常是我在新的Linux机器上要做的第一件事...

回答

当将zshemulate -L ksh选项一起使用时,脚本会提供正确的输出。如果所有其他方法均失败,则我们可能希望在Linux上尝试使用" zsh"。

回答

我在本地Ubuntu Hardy系统上安装了" ksh"和" pdksh"。

ii  ksh            93s+20071105-1 The real, AT&T version of the Korn shell
ii  pdksh          5.2.14-21ubunt A public domain version of the Korn shell

ksh具有我们期望的"正确"行为,而pdksh没有。我们可以检查本地Linux发行版的软件存储库中是否存在"真实的" ksh,而不是使用pdksh。默认情况下," Real Unix"操作系统将安装Korn shell的AT&T版本,而不是pdksh,它们基于AT&T Unix(System V):-)。

回答

我们必须待在ksh内吗?

即使我们使用相同的ksh,我们仍然会调用各种外部命令(grep,ps,cat等),其中的一部分将具有不同的参数以及系统之间的不同输出。我们或者必须考虑到这些差异,或者使用每个差异的GNU版本来使它们相同。

Perl编程语言最初是专门为克服此问题而设计的。
它包括unix shell程序员希望从shell程序获得的所有功能,但是
在每个Unix系统上都是相同的。我们可能没有所有这些的最新版本
系统,但是如果我们需要安装某些软件,也许最好安装perl。

回答

在我公司的一些人员提出建议之后,我们决定对代码进行以下修改。无论使用"真实" ksh(ksh88,ksh93)还是任何ksh克隆(pdksh,MSK ksh),这都给我们相同的结果。这对于bash也可以正常使用。

#!/bin/ksh
echo "a\nb" > junk
flag=false
while read x
do
    flag=true
done < junk
echo "flag = ${flag}"
exit 0

感谢jj33为先前接受的答案。

回答

产生差异的原因是内部块是在原始Shell上下文中还是在子Shell中执行。我们可以使用()和{}分组命令来控制它。就像我们在更新中一样,使用临时文件在大多数情况下都可以使用,但是如果脚本快速运行两次,或者脚本执行时没有清除文件,则会出现问题。

#!/bin/ksh
flag=false
echo "a\nb" | { while read x
do    
     flag=true
done }
echo "flag = ${flag}"
exit 0

这可能有助于解决我们在Linux ksh上遇到的问题。如果使用括号而不是括号,则将在其他ksh实现中获得Linux行为。