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

===============>>#1 票数: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机器上做的第一件事......

===============>>#2 票数: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以前接受的答案。

===============>>#3 票数:1

这是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. 下载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

===============>>#4 票数: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行为。

===============>>#5 票数: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

当pdksh没有时,ksh具有你期望的“正确”行为。 您可以检查本地Linux发行版的软件存储库中的“真实”ksh,而不是使用pdksh。 默认情况下,“真正的Unix”操作系统将安装AT&T版本的Korn shell,而不是pdksh,它们基于AT&T Unix(系统V):-)。

===============>>#6 票数:0

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

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

===============>>#7 票数:0

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

===============>>#8 票数:0

你必须留在ksh?

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

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

  ask by Andrew Stein translate from so

未解决问题?本站智能推荐:

3回复

AIX,HPUX和Solaris上的ps命令输出

我正在编写一个可移植的shell脚本来获取系统进程信息,我需要进程id,命令,pwdx(linux)。 在Linux上,我能够获得如下信息..但它在所有其他unix风格上都失败了。 我应该在AIX,HPUX和Solaris上使用什么来获取类似的信息,或者有任何跨平台命令 在Sol
3回复

此ksh代码如何工作?

如果我将这两行复制粘贴到任何.sh文件中,则脚本可以正常工作而不会出现任何问题。 第二行中的${?}返回0。 $XYZ可以用任何随机字符串替换。 该变量不需要定义或初始化。 但是,相同的代码对某些用户不起作用。 第一行抛出错误“ scriptname.sh[425]: : cann
1回复

不同ksh环境下的赋值变量

我有一个脚本需要在(主要)3环境下运行(AIX,Linux [Red Hat],sun [几乎不再由于迁移])但总是在ksh(不是ksh93)下 我尝试为可以在3环境中工作的变量赋值,尤其是像wc -l或sed/awk这样的操作,... 由于规范和shell解释,我找不到这个的通用代
3回复

Shell脚本在ksh中给出错误

我有一个脚本,该脚本在Bash shell(与Red Hat Linux)中执行时运行良好,但是,该脚本在使用ksh执行该脚本的Solaris 10(DB)服务器上失败。 该脚本基本上从文件中逐行读取并执行存储的proc(在Oracle中)。 下面是我的脚本: 我得到的错误是:
4回复

在KSH中生成12位十六进制数字

我需要在Solaris的KSH中生成12位十六进制数字 谢谢
3回复

在ksh中获取字符串的最后n个字符

假设我有一个包含一些字符串值的变量name 要获取最后n个字符,在bash中我们写: 什么是ksh的等效方式,我已经看过sed和awk方法,但我正在寻找的是一行或管道解决方案类似于bash来提取最后一个字符 到目前为止,这些是错误和努力: 我目前在Solaris上 -
2回复

存储数组值Unix Solaris Korn Shell时出现语法错误问题

这是我在shell脚本中的命令。 第818行的语法错误:`('意外 如果我删除这条线,它的工作 注意:当我在Solaris上尝试运行该脚本时,该脚本将在Linux OS中运行,并引发错误。
1回复

阵列无法在AIX KSH中使用

我有代码: 那么,如何打印数组的单个元素? 它适用于HPUX。 目标是并排创建2个数组,其中一个是文件名,另一个是时间创建的,以便可以检查该文件的时间。
2回复

在aix ksh中“ if [-z $ var]”的输出错误

我在脚本中使用了“ if [-z $ var]”,但是当我在aix ksh中运行它时,结果是完全错误的,并且似乎有sytax错误。 aixtest:/tmp# ls -a . .. a.sh b.sh aixtest:/tmp# ls -a | grep -i abc aixte
1回复

在AIX(ksh)中存在大量文件的情况下rm *如何工作

在AIX中可以传递给rm命令的参数是否有限制? 我用ksh。 我试着跑 在一个目录中有> 500 000个(现在)文件,但是我收到奇怪的错误。 如果我没记错的话,那就像是“内存核心转储”。 这是什么意思? 我可以假设删除了一些文件吗? 我不知道执行此命令之前有多少文件。