我参与了将包含数百个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”。
我的问题是:
其他说明:
下表总结了系统问题:
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以前接受的答案。
答案 0 :(得分: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机器上做的第一件事......
答案 1 :(得分: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以前接受的答案。
答案 2 :(得分: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
ksh具有您期望的“正确”行为,而pdksh则没有。您可以检查本地Linux发行版的软件存储库中的“真实”ksh,而不是使用pdksh。默认情况下,“真正的Unix”操作系统将安装AT&amp; T版本的Korn shell,而不是pdksh,它们基于AT&amp; T Unix(系统V): - )。
答案 3 :(得分: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行为。
答案 4 :(得分:1)
这是echo“\ n”问题的另一种解决方案
<强>步骤:强>
$ 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
OR
./ora_db_start_stop.sh START ONE_OR_MORE
==============
./ora_db_start_stop.sh STOP ALL
OR
./ora_db_start_stop.sh STOP ONE_OR_MORE
答案 5 :(得分:0)
我不知道强迫ksh与特定旧版本兼容的任何特定选项。也就是说,也许你可以在你的linux机器上安装一个非常旧版本的ksh,并让它以兼容的方式运行?
在AIX / HP-UX机器上安装更现代版本的amy shell可能更容易,只需迁移脚本即可使用sh。我知道有适用于所有平台的bash版本。
答案 6 :(得分:0)
当zsh
与emulate -L ksh
选项一起使用时,您的脚本会提供正确的(true)输出。如果所有其他方法都失败了,您可以尝试在Linux上使用zsh
。
答案 7 :(得分:0)
你必须留在ksh内吗?
即使您使用相同的ksh,您仍然会调用各种外部命令(grep,ps,cat等等),它们中的一部分将具有不同的参数和不同的系统输出。要么你必须考虑到这些差异,要么使用每个差异的GNU版本来使事情变得相同。
Perl编程语言最初的设计完全是为了解决这个问题。 它包含了unix shell程序员从shell程序中想要的所有功能 在每个Unix系统上都是一样的。您可能没有所有这些版本的最新版本 系统,但如果你需要安装一些东西,也许最好安装perl。