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

StackOverflow https://stackoverflow.com/questions/74372

  •  09-06-2019
  •  | 
  •  

我参与了将包含数百个 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像另一个操作系统一样行为?如果失败:
  • 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 之前接受的答案。

有帮助吗?

解决方案 2

在听取了公司人员的一些建议后,我们决定对代码进行以下修改。无论是使用“真正的”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 是原始的 korn shell,其历史可以追溯到 25 年前(由 David Korn 编写)。AIX 和 Solaris 使用原始 ksh 的版本,因此 kornshell.org 版本通常具有完整的功能和错误。在接触了 SunOS/Solaris 后,安装 kornshell.org ksh 通常是我在新 Linux 机器上做的第一件事......

我在本地 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&T 版本的 Korn shell,而不是 pdksh,因为它们基于 AT&T Unix(系统 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 " " 问题的另一种解决方案

脚步:

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

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

用法:开始

./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 有适用于所有平台的版本。

您的脚本在以下情况下给出正确(真实)的输出: zsh 与使用 emulate -L ksh 选项。如果所有其他方法都失败,您可能希望尝试使用 zsh 在 Linux 上。

一定要呆在ksh以内吗?

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

珀尔 编程语言最初就是为了解决这个问题而设计的。它包含Unix Shell程序员从He Shell程序中想要的所有功能,但在每个Unix系统上都是相同的。您可能没有所有这些系统上的最新版本,但是如果您需要安装某些内容,则最好安装Perl。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top