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

我参与了将包含几百个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”。

我的问题是:

  • 是否有一个环境variables,我可以设置让Linux的ksh行为像其他奥斯的'? 否则:
  • 在Linux的ksh上有没有一个选项来获得所需的行为? 否则:
  • 有一个ksh实现可用于Linux与所需的行为?

其他说明:

  • 在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是一致的,给出了不正确的(从我的angular度来看)“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 

更新

经过我公司的人的一些build议,我们决定对代码进行如下修改。 无论使用“真实”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以前接受的答案。

而不是在linux上使用pdksh,使用kornshell.org上的“真正的”ksh。 pdksh是ksh的盲目重新实现。 kornshell.org是可以追溯到25年左右的原始科恩贝壳(大卫·科恩的作品)。 AIX和Solaris使用原始版本的ksh,因此kornshell.org版本通常是功能和错误的完整版本。 在使用SunOS / Solaris之后,安装kornshell.org ksh通常是我在新的Linux机器上做的第一件事情。

经过我公司的人的一些建议,我们决定对代码进行如下修改。 无论使用“真实”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。

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

不同的原因在于,内部块是在原始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行为。

这是echo“\ 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. down load 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

$ 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安装后

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

用法:START

./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

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

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

zshemulate -L ksh选项一起使用时,您的脚本会给出正确的(true)输出。 如果一切都失败了,你可能希望尝试在Linux上使用zsh

你必须留在ksh内吗?

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

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