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

时间:2008-09-16 16:43:06

标签: linux solaris ksh aix

我参与了将包含数百个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上,Linux上的输出为“flag = true”,输出为“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以前接受的答案。

8 个答案:

答案 0 :(得分:7)

不要在linux上使用pdksh,而是使用kornshell.org中的“real”ksh。 pdksh是对ksh的盲目重新实现。 kornshell.org是可以追溯到25年左右的原始korn shell(由David Korn编写的)。 AIX和Solaris使用原始ksh的版本,因此kornshell.org版本通常是功能和错误完成的。在使用SunOS / Solaris时,安装kornshell.org ksh通常是我在新Linux机器上做的第一件事......

答案 1 :(得分:3)

在我公司的人员提出一些建议后,我们决定对代码进行以下修改。无论是使用“真实”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以前接受的答案。

答案 2 :(得分:1)

我在我的本地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。默认情况下,“真正的Unix”操作系统将安装AT&amp; T版本的Korn shell,而不是pdksh,它们基于AT&amp; T Unix(系统V): - )。

答案 3 :(得分:1)

差异的原因是内部块是在原始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行为。

答案 4 :(得分:1)

这是echo“\ n”问题的另一种解决方案

<强>步骤:

  1. 查找ksh包名称
  2. $ rpm -qa --queryformat "%{NAME}-%{VERSION}-%{RELEASE}(%{ARCH})\n" | grep "ksh" ksh-20100621-19.el6_4.3(x86_64)

    1. 卸载ksh $ sudo yum remove ksh-20100621-19.el6_4.3.x86_64

    2. 下载pdksh-5.2.14-37.el5_8.1.x86_64.rpm(请检查操作系统是否为32位或64位并选择正确的pkg)

    3. 安装pdksh-5.2.14-37.el5_8.1.x86_64.rpm

    4. $ sudo yum -y install /SCRIPT_PATH/pdksh-5.2.14-37.el5_8.1.x86_64.rpm

      安装PDKSH之前的输出

      $ ora_db_start_stop.sh
      \n==============
      Usage: START
      ==============\n\n
      ./ora_db_start_stop.sh START ALL    \n
      OR \n
      ./ora_db_start_stop.sh START ONE_OR_MORE    \n
      \n==============
      Usage: STOP
      ==============\n\n
      ./ora_db_start_stop.sh STOP ALL    \n
      OR \n
      ./ora_db_start_stop.sh STOP ONE_OR_MORE    \n\n
      

      安装PDKSH后

      ==============

      用法:开始

      ./ora_db_start_stop.sh START ALL

      OR

      ./ora_db_start_stop.sh START ONE_OR_MORE

      ==============

      用法:STOP

      ./ora_db_start_stop.sh STOP ALL

      OR

      ./ora_db_start_stop.sh STOP ONE_OR_MORE

答案 5 :(得分:0)

我不知道强迫ksh与特定旧版本兼容的任何特定选项。也就是说,也许你可以在你的linux机器上安装一个非常旧版本的ksh,并让它以兼容的方式运行?

在AIX / HP-UX机器上安装更现代版本的amy shell可能更容易,只需迁移脚本即可使用sh。我知道有适用于所有平台的bash版本。

答案 6 :(得分:0)

zshemulate -L ksh选项一起使用时,您的脚本会提供正确的(true)输出。如果所有其他方法都失败了,您可以尝试在Linux上使用zsh

答案 7 :(得分:0)

你必须留在ksh内吗?

即使您使用相同的ksh,您仍然会调用各种外部命令(grep,ps,cat等等),它们中的一部分将具有不同的参数和不同的系统输出。要么你必须考虑到这些差异,要么使用每个差异的GNU版本来使事情变得相同。

Perl编程语言最初的设计完全是为了解决这个问题。 它包含了unix shell程序员从shell程序中想要的所有功能 在每个Unix系统上都是一样的。您可能没有所有这些版本的最新版本 系统,但如果你需要安装一些东西,也许最好安装perl。