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

     2023-03-15     188

关键词:

【中文标题】如何克服 Linux 上的 ksh 与 AIX/Solaris/HPUX 上安装的 ksh 之间的不兼容问题?【英文标题】:How to overcome an incompatibility between the ksh on Linux vs. that installed on AIX/Solaris/HPUX? 【发布时间】:2010-09-09 14:48:25 【问题描述】:

我参与了将包含数百个 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 之前接受的答案。

【问题讨论】:

您使用的是哪个 Linux 发行版?这对如何获得“正确”的 ksh 产生了影响 这个问题非常相关:***.com/questions/124167/bash-variable-scope 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

不要在 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 机器上做的第一件事......

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

【讨论】:

【参考方案5】:

你必须留在 ksh 内吗?

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

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

【讨论】:

只要你使用POSIX命令,外部命令通常是相当一致的。如果您在 Linux 上设置 POSIXLY_CORRECT=1 变量并在 HP-UX 上设置 UNIX95=1(您通常可以在所有平台上同时设置这两个变量),那么外部命令的行为都相同。如果你坚持使用 ksh93,与 88 相比,你将获得与 perl 相媲美的功能水平。【参考方案6】:

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

【讨论】:

您可以使用命名管道代替临时文件。【参考方案7】:

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

【讨论】:

感谢您的建议。不幸的是,这与我想要的相反 :-) 我正在尝试将我们所有的脚本从其他 Unix 移植到 Linux....【参考方案8】:

这里是 echo "\n" 问题的另一种解决方案

步骤:

    查找 ksh 包名

$ rpm -qa --queryformat "%NAME-%VERSION-%RELEASE(%ARCH)\n" | grep "ksh" ksh-20100621-19.el6_4.3(x86_64)

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

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

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

【讨论】:

在 AIX/bash 上的 bash 循环中读取文件比在 Linux/ksh 中慢得多 - BLOCKSIZE?

】在AIX/bash上的bash循环中读取文件比在Linux/ksh中慢得多-BLOCKSIZE?【英文标题】:ReadingfileinbashlooponAIX/bashismuchslowerthaninLinux/ksh-BLOCKSIZE?【发布时间】:2018-04-2511:15:53【问题描述】:我们有一个在RHELLinux中开发的自定义脚本(在ksh... 查看详情

如何克服 Windows 2012 R2 服务器上的 405 后错误

】如何克服Windows2012R2服务器上的405后错误【英文标题】:Howtoovercomeapost405erroronwindows2012R2server【发布时间】:2021-02-2207:17:55【问题描述】:我有一个小型测试应用程序来记录相机并将文件发送到我服务器上的目录。主要文件如下... 查看详情

如何在 Typescript 中使用动态枚举器(上限量词)克服枚举类型上的 TS2589

】如何在Typescript中使用动态枚举器(上限量词)克服枚举类型上的TS2589【英文标题】:HowtoovercomeTS2589onEnumeratetypewithdynamicEnumerator(upperlimitquantifiernumber)inTypescript【发布时间】:2021-04-1021:29:31【问题描述】:查看Isitpossibletorestrictnu... 查看详情

克服下载 CSV 文件进行解析时的问题。 Linux 与 Windows 换行符

】克服下载CSV文件进行解析时的问题。Linux与Windows换行符【英文标题】:OvercomingIssuesWhenDownloadingaCSVFileforParsing.LinuxvsWindowsNewLineCharachter【发布时间】:2017-11-1605:32:41【问题描述】:我正在尝试使用历史股票价格分析股票数据。这... 查看详情

有啥方法可以在 Linux/AIX 中从 ksh 更改进程名称?

】有啥方法可以在Linux/AIX中从ksh更改进程名称?【英文标题】:IsthereanywayIcanchangeprocessnamefromkshinLinux/AIX?有什么方法可以在Linux/AIX中从ksh更改进程名称?【发布时间】:2021-08-2709:49:04【问题描述】:有什么方法可以将进程名称从k... 查看详情

linux报错:-ksh:xxxx:notfound[nosuchfileordirectory]

1.已经cd到了脚本所在的目录2.用./xxxx可以正常执行3.用/bin/kshxxxx可以正常执行4.脚本的第一行是#!/bin/ksh请帮忙看看是什么原因,谢谢。没看懂你说的啥意思?使用文件路径执行文件ok,那就没以后问题。kshfileName执行也没有问题。... 查看详情

Linux 上的程序如何与 X11 Server 通信?

】Linux上的程序如何与X11Server通信?【英文标题】:HowdoesaprogramcommunicatewiththeX11ServeronLinux?【发布时间】:2020-04-0302:53:41【问题描述】:所以我对此进行了大量研究,但找不到答案。它是否使用命名管道?本地主机上的套接字?d-... 查看详情

阅读方法:如何克服默读

阅读方法:如何克服默读      默读,面对‘文字内容’时,喉咙完成了发音的全部动作、只是不发出声音。每个“文字”,对应着“特定的声音”。    把“文字内容”当成“图片”。    对... 查看详情

如何将 Perl 变量返回到 ksh 脚本?

】如何将Perl变量返回到ksh脚本?【英文标题】:HowdoIreturnaPerlvariabletoakshscript?【发布时间】:2010-03-1419:52:51【问题描述】:我有一个调用Perl程序的ksh脚本。Perl程序创建了一些ksh脚本需要对其进行操作的重要数据。示例:我的ksh... 查看详情

linuxshell都有哪些类型

...新功能,是目前很多UNIX系统标准配置的Shell,在这些系统上的/bin/sh往往是指向/bin/ksh的符号链接。BourneAgainShell即bash由GNU项目组开发,主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,bash从csh和ksh借鉴了很多功能,是各种Li... 查看详情

如何克服死锁

】如何克服死锁【英文标题】:Howtoovercomedeadlocks【发布时间】:2012-09-0519:41:57【问题描述】:我在尝试运行包含删除语句的存储过程时收到死锁错误。发生的事情是我有一个FK约束表行,该行与我要删除的与之相关的表行同时更... 查看详情

学习-如何克服拖延

  如今,拖延的现象变得十分普遍:暑假将尽,但是老师留的作业我们才刚刚开始做;老板指派了一个任务,临近截止日期时我们才开启“拼命模式”,连夜把报告赶出来;制定计划每天要完成一百个单词的背诵,但大部分时... 查看详情

如何从 ksh 脚本执行 Derby DB 的 SQL 脚本

】如何从ksh脚本执行DerbyDB的SQL脚本【英文标题】:HowtoexecuteanSQLscriptforDerbyDBfromakshscript【发布时间】:2015-12-1616:16:29【问题描述】:我正在尝试编写一个小程序,该程序利用我编写的sql脚本从ksh脚本中访问DerbyDB(我们称之为“my... 查看详情

如何删除 ksh 中字符串变量的最后一个字符?

】如何删除ksh中字符串变量的最后一个字符?【英文标题】:HowcanIremovethelastcharacterofastringvariableinksh?【发布时间】:2012-03-0100:35:41【问题描述】:我有一个字符串变量,我想删除它的最后一个字符。例如:从“testing1”传递到“... 查看详情

如何克服 Snowflake SQL UDTF 相关子查询错误?

】如何克服SnowflakeSQLUDTF相关子查询错误?【英文标题】:HowtogetpastSnowflakeSQLUDTFcorrelatedsubqueryerror?【发布时间】:2020-07-0811:22:54【问题描述】:我定义了以下UDTF,我已确认查询与函数分开工作。CREATEORREPLACEFUNCTIONUDF_RETAINED_CUST(peri... 查看详情

如何克服焦虑?

焦虑是内心一种由于内心冲突而产生的不愉快的状态。而这段话又澄清了,焦虑不仅仅是害怕,而是出于对于不确定的恐惧以及对未来(将要发生的)的害怕。焦虑是对一种不确定的危险来源而产生的情绪。其实,不同种类的焦... 查看详情

如何在 Linux 中监视串行端口上的数据?

】如何在Linux中监视串行端口上的数据?【英文标题】:HowcanImonitordataonaserialportinLinux?【发布时间】:2010-10-3017:38:35【问题描述】:我正在调试与串行设备的通信,我需要查看双向流动的所有数据。在Linux上这似乎应该很容易,... 查看详情

退出所有调用的 KornShell (ksh) 脚本

...布时间】:2014-01-0821:44:22【问题描述】:KornShell(ksh)脚本如何退出/杀死从另一个ksh脚本启动的所有进程?如果scriptA.ksh调用scriptB.ksh那么下面的代码就足够了,但是有没有更好的解决方案呢?:scriptA.ksh:#callscriptBSnippe 查看详情