Linux 上の ksh と Linux 上の ksh の間の非互換性を克服する方法AIX/Solaris/HPUX にインストールされていますか?
質問
私は、数百の ksh スクリプトを含むシステムを AIX、Solaris、HPUX から Linux に移植するプロセスに携わっています。2 つのシステム上で 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を他の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 に感謝します。
解決 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 は、25 年ほど前に遡るオリジナルの korn シェルです (David Korn によって作成されたもの)。AIX と Solaris はオリジナルの ksh のバージョンを使用するため、kornshell.org バージョンは通常、機能とバグが完全です。SunOS/Solaris を使い始めたので、kornshell.org ksh のインストールは、通常、新しい Linux ボックスで最初に行うことの 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 はそうではありません。pdksh を使用する代わりに、ローカル Linux ディストリビューションのソフトウェア リポジトリで「本物の」 ksh を確認することもできます。「Real Unix」OS は、AT&T Unix (System V) をベースにしているため、デフォルトでは pdksh ではなく、AT&T バージョンの Korn シェルをインストールすることになります :-)。
違いの理由は、内部ブロックが元のシェル コンテキストで実行されるか、サブシェルで実行されるかです。() および {} グループ化コマンドを使用してこれを制御できる場合があります。更新時と同様に一時ファイルを使用すると、ほとんどの場合機能しますが、スクリプトが急速に 2 回実行された場合、またはファイルをクリアせずに実行された場合などに問題が発生します。
#!/bin/ksh
flag=false
echo "a\nb" | { while read x
do
flag=true
done }
echo "flag = ${flag}"
exit 0
これは、Linux ksh で発生していた問題の解決に役立つ可能性があります。中括弧の代わりに括弧を使用すると、他の ksh 実装で Linux の動作が得られます。
これは、エコー「 」問題の別の解決策です。
手順:
- 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 をダウンロードします (OS が 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
ksh を特定の古いバージョンと互換性を持たせるための特定のオプションはわかりません。そうは言っても、非常に古いバージョンの ksh を Linux ボックスにインストールして、互換性のある方法で動作させることはできるでしょうか?
AIX/HP-UX ボックスに最新バージョンの amy シェルをインストールし、sh を使用するようにスクリプトを移行する方が簡単かもしれません。すべてのプラットフォームで利用できる bash のバージョンがあることは知っています。
スクリプトは、次の場合に正しい (真の) 出力を返します。 zsh
と一緒に使用されます emulate -L ksh
オプション。他のすべてが失敗した場合は、次の方法を試してみることをお勧めします zsh
Linux 上で。
ksh内にとどまる必要がありますか?
同じ ksh を使用する場合でも、あらゆる種類の外部コマンド (grep、ps、cat など) を呼び出すことになりますが、その一部にはシステムごとに異なるパラメーターと異なる出力が含まれます。これらの違いを考慮するか、同じにするためにそれぞれの GNU バージョンを使用する必要があります。
の パール プログラミング言語は元々、まさにこの問題を克服するために設計されました。UNIXシェルプログラマーがHEシェルプログラムに望むすべての機能が含まれていますが、すべてのUNIXシステムで同じです。これらすべてのシステムに最新バージョンがない場合がありますが、何かをインストールする必要がある場合は、Perlをインストールする方が良いかもしれません。