代码之家  ›  专栏  ›  技术社区  ›  Andrew Stein

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

  •  6
  • Andrew Stein  · 技术社区  · 17 年前

    我参与了将包含数百个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表现得像 其他O?如果失败:
    • 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 回复  |  直到 17 年前
        1
  •  7
  •   jj33    17 年前

    不要在linux上使用pdksh,而是使用来自kornshell.org的“真实”ksh。pdksh是ksh的盲目重新实现。kornshell.org是大约25年前的原始korn shell(由David korn撰写)。AIX和Solaris使用原始ksh的版本,因此kornshell.org版本通常具有完整的功能和错误。在接触了SunOS/Solaris之后,安装kornshell.org ksh通常是我在新的Linux机器上做的第一件事。..

        2
  •  3
  •   Andrew Stein    17 年前

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

        3
  •  1
  •   jtimberman    17 年前

    我在本地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&Korn shell的T版本,而不是pdksh,默认情况下,它们基于AT&T Unix(System V):-)。

        4
  •  1
  •   mpez0    17 年前

    你必须呆在ksh吗?

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

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

        5
  •  1
  •   Amicable    12 年前

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

        6
  •  0
  •   zigdon    17 年前

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

    步骤:

    1. 查找ksh包名称

    $ 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_64rpm(请检查操作系统是否为32位或64位,并选择正确的pkg)

    3. 安装pdksh-5.2.14-37.el5_8.1.x86_64rpm

    $ 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

    ./ora_db_start_stop.sh START ONE_OR_MORE

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

    用法:停止

    ./ora_db_start_stop.sh STOP ALL

    ./ora_db_start_stop.sh STOP ONE_OR_MORE

        7
  •  0
  •   Alex M    17 年前

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

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

        8
  •  0
  •   szabgab Brandon Fosdick    17 年前

    当满足以下条件时,您的脚本会给出正确的(真)输出 zsh emulate -L ksh 选项。如果所有其他方法都失败了,您可能希望尝试使用 原有的质量 在Linux上。

    推荐文章